Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion solver/src/main/kotlin/org/ucfs/parser/Gll.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Gll<VertexType, LabelType : ILabel> private constructor(
private fun isParseResult(matchedRange: RangeSppfNode<VertexType>): Boolean {
return matchedRange.inputRange!!.from in ctx.input.getInputStartVertices()
&& matchedRange.rsmRange!!.from == ctx.fictiveStartState
&& matchedRange.rsmRange.to == ctx.fictiveFinalState
&& matchedRange.rsmRange!!.to == ctx.fictiveFinalState
}

/**
Expand Down
2 changes: 1 addition & 1 deletion solver/src/main/kotlin/org/ucfs/parser/IGll.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ interface IGll<InputNodeType, LabelType : ILabel> {

//TODO why these parameters???
newDescriptor = Descriptor(
rangeToPop.inputRange.to, descriptor.gssNode, destinationRsmState, newSppfNode
rangeToPop.inputRange!!.to, descriptor.gssNode, destinationRsmState, newSppfNode
)
ctx.descriptors.add(newDescriptor)
}
Expand Down
27 changes: 19 additions & 8 deletions solver/src/main/kotlin/org/ucfs/sppf/SppfStorage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ open class SppfStorage<InputEdgeType> {
return createdSppfNodes.getOrPut(node, { node })
}

private fun makeNode(
input: InputRange<InputEdgeType>?,
rsm: RsmRange?,
type: RangeType
): RangeSppfNode<InputEdgeType> = when (type) {
is TerminalType<*>, is EpsilonNonterminalType, is EmptyType -> LeafSppfNode(input, rsm, type)
is IntermediateType<*> -> BinarySppfNode(input, rsm, type)
else -> VariadicSppfNode(input, rsm, type) // Range, NonterminalType
}

/**
* Add nonterminal node after pop
*/
Expand Down Expand Up @@ -63,7 +73,7 @@ open class SppfStorage<InputEdgeType> {
), RsmRange(
leftSubtree.rsmRange!!.from, rightSubtree.rsmRange!!.to
), IntermediateType(
leftSubtree.rsmRange.to, leftSubtree.inputRange.to
leftSubtree.rsmRange!!.to, leftSubtree.inputRange!!.to
), listOf(leftSubtree, rightSubtree)
)
}
Expand All @@ -74,17 +84,18 @@ open class SppfStorage<InputEdgeType> {
rangeType: RangeType,
children: List<RangeSppfNode<InputEdgeType>> = listOf()
): RangeSppfNode<InputEdgeType> {
val rangeNode = addNode(RangeSppfNode(input, rsm, Range))
val rangeNode = addNode(makeNode(input, rsm, Range))
val valueRsm = if (rangeType is TerminalType<*>) null else rsm
val valueNode = addNode(RangeSppfNode(input, valueRsm, rangeType))
if (!rangeNode.children.contains(valueNode)) {
rangeNode.children.add(valueNode)
val valueNode = addNode(makeNode(input, valueRsm, rangeType))

if (!rangeNode.hasChild(valueNode)) {
rangeNode.addChild(valueNode)
}
for (child in children) {
if (!valueNode.children.contains(child)) {
valueNode.children.add(child)
if (!valueNode.hasChild(child)) {
valueNode.addChild(child)
}
}
return rangeNode
}
}
}
4 changes: 2 additions & 2 deletions solver/src/main/kotlin/org/ucfs/sppf/buildStringFromSppf.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fun <InputNode>buildTokenStreamFromSppf(sppfNode: RangeSppfNode<InputNode>): Mut
}

is NonterminalType -> {
if (curNode.children.isNotEmpty()) {
if (curNode.children.toList().isNotEmpty()) {
curNode.children.findLast {
!visited.contains(
it
Expand All @@ -50,4 +50,4 @@ fun <InputNode>buildTokenStreamFromSppf(sppfNode: RangeSppfNode<InputNode>): Mut
*/
fun <InputNode> buildStringFromSppf(sppfNode: RangeSppfNode<InputNode>): String {
return buildTokenStreamFromSppf(sppfNode).joinToString(separator = "")
}
}
109 changes: 94 additions & 15 deletions solver/src/main/kotlin/org/ucfs/sppf/node/RangeSppfNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,111 @@ import org.ucfs.rsm.RsmState
import org.ucfs.rsm.symbol.ITerminal

/**
* Base class for SPPF range nodes.
* Represents all possible ways to derive a specific range.
* Contains two ranges: one in the RSM and one in the input graph.
* Nodes are deduplicated via [SppfStorage] and can be reused.
*
* Specialized into three subclasses based on the number of children:
* - [LeafSppfNode] — no children (terminal, epsilon, empty nodes)
* - [BinarySppfNode] — exactly two children (intermediate nodes)
* - [VariadicSppfNode] — variable number of children (range, nonterminal nodes)
*
* A Range node which corresponds to a matched range. It
* represents all possible ways to get a specific range and can
* have arbitrary many children. A child node can be of any
* type, besides a Range node. Nodes of this type can be reused.
* <p>
* Contains two range: in RSM and in Input graph
*<p>
* May be used as extended packed sppfNode.
* @param VertexType - type of vertex in input graph
*/
sealed class RangeSppfNode<VertexType> {
abstract val inputRange: InputRange<VertexType>?
abstract val rsmRange: RsmRange?
abstract val type: RangeType
abstract fun hasChild(target: RangeSppfNode<VertexType>): Boolean
abstract fun addChild(child: RangeSppfNode<VertexType>)
abstract val children: Iterable<RangeSppfNode<VertexType>>
}

data class RangeSppfNode<VertexType>(
val inputRange: InputRange<VertexType>?,
val rsmRange: RsmRange?,
val type: RangeType,
) {
val children = ArrayList<RangeSppfNode<VertexType>>()
data class LeafSppfNode<VertexType>(
override val inputRange: InputRange<VertexType>?,
override val rsmRange: RsmRange?,
override val type: RangeType,
) : RangeSppfNode<VertexType>() {
override val children = emptyList<RangeSppfNode<VertexType>>()

override fun hasChild(target: RangeSppfNode<VertexType>) = false

override fun addChild(child: RangeSppfNode<VertexType>) = throw UnsupportedOperationException()
}

data class BinarySppfNode<VertexType>(
override val inputRange: InputRange<VertexType>?,
override val rsmRange: RsmRange?,
override val type: RangeType,
) : RangeSppfNode<VertexType>() {
var child0: RangeSppfNode<VertexType>? = null
var child1: RangeSppfNode<VertexType>? = null

override val children: Iterable<RangeSppfNode<VertexType>> get() = listOfNotNull(child0, child1)

override fun hasChild(target: RangeSppfNode<VertexType>) =
child0 === target || child1 === target

override fun addChild(child: RangeSppfNode<VertexType>) {
when {
child0 == null -> child0 = child
child1 == null -> child1 = child
else -> throw IllegalStateException("BinarySppfNode already has 2 children")
}
}
}

data class VariadicSppfNode<VertexType>(
override val inputRange: InputRange<VertexType>?,
override val rsmRange: RsmRange?,
override val type: RangeType,
) : RangeSppfNode<VertexType>() {
private var _child0: RangeSppfNode<VertexType>? = null
private var _child1: RangeSppfNode<VertexType>? = null
private var _rest: ArrayList<RangeSppfNode<VertexType>>? = null
private var _size = 0

override val children: Iterable<RangeSppfNode<VertexType>> get() = object : Iterable<RangeSppfNode<VertexType>> {
override fun iterator() = object : Iterator<RangeSppfNode<VertexType>> {
var i = 0

override fun hasNext() = i < _size

override fun next(): RangeSppfNode<VertexType> = when (i++) {
0 -> _child0!!
1 -> _child1!!
else -> _rest!![i - 3]
}
}
}

override fun hasChild(target: RangeSppfNode<VertexType>): Boolean {
if (_child0 === target) return true
if (_child1 === target) return true
_rest?.forEach { if (it === target) return true }
return false
}

override fun addChild(child: RangeSppfNode<VertexType>) {
when (_size) {
0 -> _child0 = child
1 -> _child1 = child
else -> {
if (_rest == null) _rest = ArrayList(2)
_rest!!.add(child)
}
}
_size++
}
}

fun <VertexType> getEmptyRange( isStart: Boolean = false): RangeSppfNode<VertexType> {
val type = EmptyType()
if(isStart) {
type.isStart = isStart
}
return RangeSppfNode(null, null, type)
return LeafSppfNode(null, null, type)
}

data class InputRange<VertexType>(
Expand Down
2 changes: 1 addition & 1 deletion solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fun <InputNode> getSppfDot(sppfNodes: Set<RangeSppfNode<InputNode>>, label: Stri
sb.appendLine("labelloc=\"t\"")
sb.appendLine("label=\"$label\"")
var idx = 0
val results = sppfNodes.sortedWith(compareBy { it.toString() }).map { sppf -> getSppfDot(sppf.children[0], idx++.toString()) }
val results = sppfNodes.sortedWith(compareBy { it.toString() }).map { sppf -> getSppfDot(sppf.children.first(), idx++.toString()) }
for (sppf in results.sorted()) {
sb.appendLine(sppf)
}
Expand Down