From 75eb9b485130d1ec3e89496f9e9a61eb524ee9d7 Mon Sep 17 00:00:00 2001 From: Olga Bachishe Date: Sun, 19 Jan 2025 21:29:07 +0300 Subject: [PATCH] smth is changed --- .../kotlin/org/ucfs/Java8ParserRecovery.kt | 5 +- .../kotlin/org/ucfs/parser/GeneratedParser.kt | 14 +- .../src/main/kotlin/org/ucfs/gss/GssNode.kt | 6 +- solver/src/main/kotlin/org/ucfs/parser/Gll.kt | 19 ++- .../src/main/kotlin/org/ucfs/parser/IGll.kt | 49 ++++--- .../org/ucfs/parser/context/IContext.kt | 14 +- .../main/kotlin/org/ucfs/sppf/RecoverySppf.kt | 4 +- solver/src/main/kotlin/org/ucfs/sppf/Sppf.kt | 126 ++++++++---------- .../ucfs/sppf/node/IntermediateSppfNode.kt | 7 +- .../org/ucfs/sppf/node/NonterminalSppfNode.kt | 2 +- .../org/ucfs/sppf/node/PackedSppfNode.kt | 10 +- .../kotlin/org/ucfs/sppf/node/SppfNode.kt | 5 - .../org/ucfs/sppf/node/SymbolSppfNode.kt | 12 +- .../kotlin/org/ucfs/sppf/writeSppfToDot.kt | 2 - .../main/kotlin/org/ucfs/IDynamicGllTest.kt | 1 + .../src/test/kotlin/solver/GllRsmTest.kt | 26 +++- .../resources/grammars/ambiguous/grammar.rsm | 12 +- 17 files changed, 156 insertions(+), 158 deletions(-) diff --git a/benchmarks/src/main/kotlin/org/ucfs/Java8ParserRecovery.kt b/benchmarks/src/main/kotlin/org/ucfs/Java8ParserRecovery.kt index 002fc2c9e..15a29e389 100644 --- a/benchmarks/src/main/kotlin/org/ucfs/Java8ParserRecovery.kt +++ b/benchmarks/src/main/kotlin/org/ucfs/Java8ParserRecovery.kt @@ -2,7 +2,6 @@ package org.ucfs -import org.ucfs.JavaToken import org.ucfs.descriptors.Descriptor import org.ucfs.input.IInputGraph import org.ucfs.input.ILabel @@ -8649,8 +8648,8 @@ public class Java8ParserRecovery : } } - override fun parse(descriptor: Descriptor) { - super.parse(descriptor) + override fun handleDescriptor(descriptor: Descriptor) { + super.handleDescriptor(descriptor) org.ucfs.intersection.RecoveryIntersection.handleRecoveryEdges(this, descriptor) } diff --git a/generator/src/main/kotlin/org/ucfs/parser/GeneratedParser.kt b/generator/src/main/kotlin/org/ucfs/parser/GeneratedParser.kt index 8fd160aba..ff93e7661 100644 --- a/generator/src/main/kotlin/org/ucfs/parser/GeneratedParser.kt +++ b/generator/src/main/kotlin/org/ucfs/parser/GeneratedParser.kt @@ -26,15 +26,13 @@ abstract class GeneratedParser : curSppfNode: SppfNode? ): Unit - override fun parse(descriptor: Descriptor) { + override fun handleDescriptor(descriptor: Descriptor) { val state = descriptor.rsmState val nt = state.nonterminal val pos = descriptor.inputPosition val curSppfNode = descriptor.sppfNode val epsilonSppfNode = ctx.sppf.getEpsilonSppfNode(descriptor) - val leftExtent = curSppfNode?.leftExtent - val rightExtent = curSppfNode?.rightExtent if (state.isFinal) { pop(descriptor.gssNode, curSppfNode ?: epsilonSppfNode, pos) @@ -42,16 +40,6 @@ abstract class GeneratedParser : ctx.descriptors.addToHandled(descriptor) - if (state.isStart && state.isFinal) { - checkAcceptance( - epsilonSppfNode, - epsilonSppfNode!!.leftExtent, - epsilonSppfNode!!.rightExtent, - nt - ) - } - checkAcceptance(curSppfNode, leftExtent, rightExtent, nt) - callNtFuncs(nt, descriptor, curSppfNode) } diff --git a/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt b/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt index 86d74c6f3..598e41f8e 100644 --- a/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt +++ b/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt @@ -28,7 +28,7 @@ class GssNode( /** * Maps edge label (rsmState, sppfNode) to destination gssNode */ - val edges: HashMap?>, HashSet>> = HashMap() + val edges: HashMap?>, GssNode> = HashMap() /** * Stores handled descriptors, which contained current gssNode as value of corresponding field @@ -40,12 +40,10 @@ class GssNode( * @param rsmState - rsmState to store on the edge * @param sppfNode - sppfNode to store on the edge * @param gssNode - destination gssNode - * @return true if creation was successful, false otherwise */ fun addEdge(rsmState: RsmState, sppfNode: SppfNode?, gssNode: GssNode): Boolean { val label = Pair(rsmState, sppfNode) - - return edges.computeIfAbsent(label) { HashSet() }.add(gssNode) + return edges.put(label, gssNode) == null } override fun toString() = "GSSNode(nonterminal=$nonterminal, inputPosition=$inputPosition)" diff --git a/solver/src/main/kotlin/org/ucfs/parser/Gll.kt b/solver/src/main/kotlin/org/ucfs/parser/Gll.kt index 410a8ecb6..325094631 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/Gll.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/Gll.kt @@ -66,26 +66,25 @@ class Gll private constructor( * Processes descriptor * @param descriptor - descriptor to process */ - override fun parse(descriptor: Descriptor) { + override fun handleDescriptor(descriptor: Descriptor) { val state = descriptor.rsmState val pos = descriptor.inputPosition val sppfNode = descriptor.sppfNode - val epsilonSppfNode = ctx.sppf.getEpsilonSppfNode(descriptor) val leftExtent = sppfNode?.leftExtent val rightExtent = sppfNode?.rightExtent if (state.isFinal) { - pop(descriptor.gssNode, sppfNode ?: epsilonSppfNode, pos) + pop(descriptor.gssNode, sppfNode ?: ctx.sppf.getEpsilonSppfNode(descriptor), pos) } ctx.descriptors.addToHandled(descriptor) - - if (state.isStart && state.isFinal) { - checkAcceptance( - epsilonSppfNode, epsilonSppfNode!!.leftExtent, epsilonSppfNode!!.rightExtent, state.nonterminal - ) - } - checkAcceptance(sppfNode, leftExtent, rightExtent, state.nonterminal) +// +// if (state.isStart && state.isFinal) { +// checkAcceptance( +// epsilonSppfNode, epsilonSppfNode!!.leftExtent, epsilonSppfNode!!.rightExtent, state.nonterminal +// ) +// } +// checkAcceptance(sppfNode, leftExtent, rightExtent, state.nonterminal) engine.handleEdges(this, descriptor, sppfNode) } diff --git a/solver/src/main/kotlin/org/ucfs/parser/IGll.kt b/solver/src/main/kotlin/org/ucfs/parser/IGll.kt index 9b4a760d1..f99702442 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/IGll.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/IGll.kt @@ -32,7 +32,7 @@ interface IGll { // Continue parsing until all default descriptors processed var curDescriptor = ctx.nextDescriptorToHandle() while (curDescriptor != null) { - parse(curDescriptor) + handleDescriptor(curDescriptor) curDescriptor = ctx.nextDescriptorToHandle() } @@ -43,7 +43,7 @@ interface IGll { * Processes descriptor * @param descriptor - descriptor to process */ - fun parse(descriptor: Descriptor) + fun handleDescriptor(descriptor: Descriptor) /** * Creates descriptors for all starting vertices in input graph @@ -104,7 +104,10 @@ interface IGll { if (ctx.poppedGssNodes.containsKey(newNode)) { for (popped in ctx.poppedGssNodes[newNode]!!) { val descriptor = Descriptor( - rsmState, gssNode, ctx.sppf.getParentNodeAfterTerminal(rsmState, sppfNode, popped!!), popped.rightExtent + rsmState, + gssNode, + ctx.sppf.getOrCreateIntermediateNode(rsmState, sppfNode, popped!!), + popped.rightExtent ) addDescriptor(descriptor) } @@ -126,21 +129,26 @@ interface IGll { * Iterates over all outgoing edges from current gssNode, collects derivation trees, stored on edges and * combines them with current derivation tree, given as sppfNode * @param gssNode - current node in top layer of Graph Structured Stack - * @param sppfNode - derivation tree, corresponding to parsed portion of input + * @param sppfNode - derivation tree, corresponding to parsed portion of input for current nonterminal * @param inputPosition - vertex in input graph */ - fun pop(gssNode: GssNode, sppfNode: SppfNode?, inputPosition: VertexType) { - if (!ctx.poppedGssNodes.containsKey(gssNode)) ctx.poppedGssNodes[gssNode] = HashSet() + fun pop(gssNode: GssNode, sppfNode: SppfNode, inputPosition: VertexType) { + if (!ctx.poppedGssNodes.containsKey(gssNode)) { + ctx.poppedGssNodes[gssNode] = HashSet() + } ctx.poppedGssNodes.getValue(gssNode).add(sppfNode) - for ((label, target) in gssNode.edges) { - for (node in target) { - val descriptor = Descriptor( - label.first, node, ctx.sppf.getParentNodeAfterTerminal(label.first, label.second, sppfNode!!), inputPosition - ) - addDescriptor(descriptor) - } + val symbolSppfNode = ctx.sppf.getOrCreateSymbolSppfNode(gssNode.nonterminal, sppfNode) + + for ((label, node) in gssNode.edges) { + val (rsmTo, leftSppf) = label + val descriptor = Descriptor( + rsmTo, node, ctx.sppf.getOrCreateIntermediateNode(rsmTo, leftSppf, symbolSppfNode), inputPosition + ) + addDescriptor(descriptor) } + + checkAcceptance(symbolSppfNode) } /** @@ -151,19 +159,18 @@ interface IGll { * @param rightExtent - right limit of the range * @param nonterminal - nonterminal, which defines language we check belonging to */ - fun checkAcceptance( - sppfNode: SppfNode?, leftExtent: VertexType?, rightExtent: VertexType?, nonterminal: Nonterminal - ) { - if (sppfNode is SymbolSppfNode && nonterminal == ctx.startState.nonterminal && ctx.input.isStart( - leftExtent!! - ) && ctx.input.isFinal(rightExtent!!) + fun checkAcceptance(sppfNode: SppfNode) { + if (sppfNode is SymbolSppfNode + && sppfNode.symbol == ctx.startState.nonterminal + && ctx.input.isStart(sppfNode.leftExtent) + && ctx.input.isFinal(sppfNode.rightExtent) ) { if (ctx.parseResult == null || ctx.parseResult!!.weight > sppfNode.weight) { ctx.parseResult = sppfNode } //update reachability - val pair = Pair(leftExtent, rightExtent) + val pair = Pair(sppfNode.leftExtent, sppfNode.rightExtent) val distance = ctx.sppf.minDistance(sppfNode) ctx.reachabilityPairs[pair] = if (ctx.reachabilityPairs.containsKey(pair)) { @@ -217,7 +224,7 @@ interface IGll { targetWeight: Int, ) { val terminalNode = ctx.sppf.getOrCreateTerminalSppfNode(terminal, descriptor.inputPosition, targetVertex, targetWeight) - val parentNode = ctx.sppf.getParentNodeAfterTerminal(targetState, sppfNode, terminalNode) + val parentNode = ctx.sppf.getOrCreateIntermediateNode(targetState, sppfNode, terminalNode) val newDescriptor = Descriptor(targetState, descriptor.gssNode, parentNode, targetVertex) addDescriptor(newDescriptor) } diff --git a/solver/src/main/kotlin/org/ucfs/parser/context/IContext.kt b/solver/src/main/kotlin/org/ucfs/parser/context/IContext.kt index 821a047f3..4bb1f5c44 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/context/IContext.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/context/IContext.kt @@ -73,12 +73,14 @@ interface IContext { val leftExtent = sppfNode?.leftExtent val rightExtent = sppfNode?.rightExtent - if (parseResult == null && sppfNode is SymbolSppfNode<*> && state.nonterminal == startState.nonterminal && input.isStart( - leftExtent!! - ) && input.isFinal(rightExtent!!) - ) { - descriptors.removeFromHandled(descriptor) - } +// if (parseResult == null +// && sppfNode is SymbolSppfNode<*> +// && state.nonterminal == startState.nonterminal +// && input.isStart(leftExtent!!) +// && input.isFinal(rightExtent!!) +// ) { +// descriptors.removeFromHandled(descriptor) +// } descriptors.addToHandling(descriptor) } diff --git a/solver/src/main/kotlin/org/ucfs/sppf/RecoverySppf.kt b/solver/src/main/kotlin/org/ucfs/sppf/RecoverySppf.kt index 771acfba3..bdf161147 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/RecoverySppf.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/RecoverySppf.kt @@ -18,12 +18,12 @@ class RecoverySppf : Sppf() { * @param nextSppfNode - right subtree * @return ParentNode, which has combined subtree as alternative derivation */ - override fun getParentNodeAfterTerminal( + override fun getOrCreateIntermediateNode( rsmState: RsmState, sppfNode: SppfNode?, nextSppfNode: SppfNode, ): SppfNode { - val parent = super.getParentNodeAfterTerminal(rsmState, sppfNode, nextSppfNode) + val parent = super.getOrCreateIntermediateNode(rsmState, sppfNode, nextSppfNode) updateWeights(parent) return parent } diff --git a/solver/src/main/kotlin/org/ucfs/sppf/Sppf.kt b/solver/src/main/kotlin/org/ucfs/sppf/Sppf.kt index 1fc440c3c..c29d4b410 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/Sppf.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/Sppf.kt @@ -28,22 +28,13 @@ open class Sppf { * @param descriptor - current parsing stage * @return created epsilonNode */ - fun getEpsilonSppfNode(descriptor: Descriptor): SppfNode? { - val rsmState = descriptor.rsmState - val sppfNode = descriptor.sppfNode - val inputPosition = descriptor.inputPosition - - return if (rsmState.isStart && rsmState.isFinal) { - // if nonterminal accepts epsilon - getParentNodeAfterTerminal( - rsmState, - sppfNode, - getOrCreateIntermediateSppfNode(rsmState, inputPosition, inputPosition, weight = 0) - ) - } else { - sppfNode - } - } + fun getEpsilonSppfNode(descriptor: Descriptor): SppfNode = + getOrCreateIntermediateSppfNode( + descriptor.rsmState, + descriptor.inputPosition, + descriptor.inputPosition, + weight = 0 + ) /** * Part of incrementality mechanism. @@ -59,15 +50,15 @@ open class Sppf { } /** - * Receives two subtrees of SPPF and connects them via PackedNode. - * If given subtrees repesent derivation tree for nonterminal and state is final, then retrieves or creates + * Receives two subtrees of SPPF where second one is terminal, and connects them via PackedNode. + * If given subtrees represent derivation tree for nonterminal and state is final, then retrieves or creates * Symbol sppfNode, otherwise retrieves or creates Intermediate sppfNode * @param rsmState - current rsmState * @param sppfNode - left subtree * @param nextSppfNode - right subtree * @return ParentNode, which has combined subtree as alternative derivation */ - open fun getParentNodeAfterTerminal( + open fun getOrCreateIntermediateNode( rsmState: RsmState, sppfNode: SppfNode?, nextSppfNode: SppfNode, @@ -76,46 +67,19 @@ open class Sppf { val leftExtent = sppfNode?.leftExtent ?: nextSppfNode.leftExtent val rightExtent = nextSppfNode.rightExtent - val packedNode = PackedSppfNode(nextSppfNode.leftExtent, rsmState, sppfNode, nextSppfNode) + val packedNode = PackedSppfNode(nextSppfNode.leftExtent, sppfNode, nextSppfNode) val parent: NonterminalSppfNode = - if (rsmState.isFinal) getOrCreateSymbolSppfNode(rsmState.nonterminal, leftExtent, rightExtent, packedNode.weight) - else getOrCreateIntermediateSppfNode(rsmState, leftExtent, rightExtent, packedNode.weight) + getOrCreateIntermediateSppfNode(rsmState, leftExtent, rightExtent, packedNode.weight) + sppfNode?.parents?.add(packedNode) + nextSppfNode.parents.add(packedNode) + packedNode.parents.add(parent) - if (sppfNode != null || parent != nextSppfNode) { // Restrict SPPF from creating loops PARENT -> PACKED -> PARENT - sppfNode?.parents?.add(packedNode) - nextSppfNode.parents.add(packedNode) - packedNode.parents.add(parent) - - parent.children.add(packedNode) - } + parent.children.add(packedNode) return parent } - - /** - *#TODO fix it for cases S = a | bc | abc - */ - private fun hasCommonSymbolInLeftExtend( - symbolSppfInLeft: SppfNode?, - rsmState: RsmState, - packedNode: PackedSppfNode - ): NonterminalSppfNode? { - if(symbolSppfInLeft is SymbolSppfNode && rsmState.isFinal){ - val commonNodes = symbolSppfInLeft.children.filter { packed -> packed.rsmState.targetStates.contains(rsmState) } - for(node in commonNodes){ - if(node.rightSppfNode == null){ - // node.rightSppfNode = - } - symbolSppfInLeft.children.remove(node) - // node. - - } - } - return null - } - /** * Creates or retrieves Terminal sppfNode with given parameters * @param terminal - terminal value @@ -167,28 +131,54 @@ open class Sppf { return createdSppfNodes[node]!! as IntermediateSppfNode } + fun getUniqueSppfNode(node: SppfNode): SppfNode { + if (!createdSppfNodes.containsKey(node)) { + createdSppfNodes[node] = node + } + + return createdSppfNodes[node]!! + } + /** - * Creates or retrieves Symbol sppfNode with given parameters - * @param nonterminal - nonterminal - * @param leftExtent - left limit of subrange - * @param rightExtent - right limit of subrange - * @param weight - weight of the node, default value is Int.MAX_VALUE + * Creates or retrieves Intermediate sppfNode with one child sppfNode. */ - fun getOrCreateSymbolSppfNode( - nonterminal: Nonterminal, - leftExtent: VertexType, - rightExtent: VertexType, - weight: Int = Int.MAX_VALUE, - ): SymbolSppfNode { - val node = SymbolSppfNode(nonterminal, leftExtent, rightExtent) + fun getOrCreateIntermediateSppfNode(rsmState: RsmState, sppfNode: SppfNode): SymbolSppfNode { + val symbolNode = getOrCreateIntermediateNode(rsmState, null, sppfNode) + val packedNode = PackedSppfNode(sppfNode.leftExtent, null, sppfNode) + symbolNode.children.add(packedNode) + return symbolNode + } + + /** + * Creates or retrieves Symbol sppfNode from given sppfNode. + * If given sppfNode is intermediate then we add its children to symbol node, + * otherwise, add given sppfNode as child. + */ + fun getOrCreateSymbolSppfNode(nonterminal: Nonterminal, sppfNode: SppfNode): SymbolSppfNode { + val intermediateSppfNode = when(sppfNode) { + is IntermediateSppfNode -> { + sppfNode + } + else -> { + getOrCreateIntermediateNode(nonterminal.startState, null, sppfNode) + } + } + val node = SymbolSppfNode(nonterminal, sppfNode) node.weight = weight - if (!createdSppfNodes.containsKey(node)) { - createdSppfNodes[node] = node + return getUniqueSppfNode(node) as SymbolSppfNode + val symbolNode = getOrCreateSymbolSppfNode(nonterminal, sppfNode.leftExtent, sppfNode.rightExtent, sppfNode.weight) + when(sppfNode) { + is IntermediateSppfNode -> { + symbolNode.children.addAll(sppfNode.children) + } + else -> { + val packedNode = PackedSppfNode(sppfNode.leftExtent, null, sppfNode) + symbolNode.children.add(packedNode) + } } - - return createdSppfNodes[node]!! as SymbolSppfNode + return symbolNode } /** diff --git a/solver/src/main/kotlin/org/ucfs/sppf/node/IntermediateSppfNode.kt b/solver/src/main/kotlin/org/ucfs/sppf/node/IntermediateSppfNode.kt index d52c77bda..b182a4dc4 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/node/IntermediateSppfNode.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/node/IntermediateSppfNode.kt @@ -2,6 +2,7 @@ package org.ucfs.sppf.node import org.ucfs.rsm.RsmState import java.util.* +import kotlin.collections.HashSet /** * An Intermediate node which corresponds to the intermediate @@ -23,8 +24,10 @@ class IntermediateSppfNode( /** * Right limit of the subrange */ - rightExtent: VertexType, + rightExtent: VertexType ) : NonterminalSppfNode(leftExtent, rightExtent) { + override val children: HashSet> = HashSet() + override fun toString() = "IntermediateSppfNode(leftExtent=$leftExtent, rightExtent=$rightExtent, rsmState=$rsmState)" override fun equals(other: Any?): Boolean { @@ -38,4 +41,6 @@ class IntermediateSppfNode( override val hashCode: Int = Objects.hash(leftExtent, rightExtent, rsmState) override fun hashCode() = hashCode + override val parents: HashSet + get() = TODO("Not yet implemented") } diff --git a/solver/src/main/kotlin/org/ucfs/sppf/node/NonterminalSppfNode.kt b/solver/src/main/kotlin/org/ucfs/sppf/node/NonterminalSppfNode.kt index 0f3a0cda4..ba4492b2e 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/node/NonterminalSppfNode.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/node/NonterminalSppfNode.kt @@ -18,5 +18,5 @@ abstract class NonterminalSppfNode( /** * Set of all children nodes */ - val children: HashSet> = HashSet() + abstract val children: HashSet> } diff --git a/solver/src/main/kotlin/org/ucfs/sppf/node/PackedSppfNode.kt b/solver/src/main/kotlin/org/ucfs/sppf/node/PackedSppfNode.kt index 11b04bc2a..dc88994bd 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/node/PackedSppfNode.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/node/PackedSppfNode.kt @@ -1,6 +1,5 @@ package org.ucfs.sppf.node -import org.ucfs.rsm.RsmState import java.util.* /** @@ -13,10 +12,6 @@ open class PackedSppfNode( * Divides subrange leftExtent - rightExtent into two subranges leftExtent - pivot, pivot - rightExtent */ val pivot: VertexType, - /** - * rsmState, corresponding to grammar slot in CFS - */ - val rsmState: RsmState, /** * Left child */ @@ -40,19 +35,18 @@ open class PackedSppfNode( override var weight: Int = (leftSppfNode?.weight ?: 0) + (rightSppfNode?.weight ?: 0) override fun toString() = - "PackedSppfNode(pivot=$pivot, rsmState=$rsmState, leftSppfNode=$leftSppfNode, rightSppfNode=$rightSppfNode)" + "PackedSppfNode(pivot=$pivot, leftSppfNode=$leftSppfNode, rightSppfNode=$rightSppfNode)" override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is PackedSppfNode<*>) return false if (pivot != other.pivot) return false - if (rsmState != other.rsmState) return false if (leftSppfNode != other.leftSppfNode) return false if (rightSppfNode != other.rightSppfNode) return false return true } - val hashCode: Int = Objects.hash(pivot, rsmState, leftSppfNode, rightSppfNode) + val hashCode: Int = Objects.hash(pivot, leftSppfNode, rightSppfNode) override fun hashCode() = hashCode } diff --git a/solver/src/main/kotlin/org/ucfs/sppf/node/SppfNode.kt b/solver/src/main/kotlin/org/ucfs/sppf/node/SppfNode.kt index aa4a43fa4..6d9ac41df 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/node/SppfNode.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/node/SppfNode.kt @@ -31,11 +31,6 @@ abstract class SppfNode( override var weight: Int, override var id: Int = SppfNodeId.getFirstFreeSppfNodeId(), ) : ISppfNode { - /** - * Set of all node that have current one as a child - */ - override val parents: HashSet = HashSet() - override fun toString() = "SppfNode(leftExtent=$leftExtent, rightExtent=$rightExtent)" override fun equals(other: Any?): Boolean { diff --git a/solver/src/main/kotlin/org/ucfs/sppf/node/SymbolSppfNode.kt b/solver/src/main/kotlin/org/ucfs/sppf/node/SymbolSppfNode.kt index 726f17910..fefbefc73 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/node/SymbolSppfNode.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/node/SymbolSppfNode.kt @@ -16,12 +16,12 @@ class SymbolSppfNode( /** * Left limit of the subrange */ - leftExtent: VertexType, - /** - * Right limit of the subrange - */ - rightExtent: VertexType, -) : NonterminalSppfNode(leftExtent, rightExtent) { + private val intermediateNode: IntermediateSppfNode +) : NonterminalSppfNode(intermediateNode.leftExtent, intermediateNode.rightExtent) { + + override val children: HashSet> + get() = intermediateNode.children + override fun toString() = "SymbolSppfNode(leftExtent=$leftExtent, rightExtent=$rightExtent, symbol=$symbol)" override fun equals(other: Any?): Boolean { diff --git a/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt b/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt index 410adae19..dc40c1a01 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt @@ -1,10 +1,8 @@ package org.ucfs.sppf import org.ucfs.sppf.node.* -import java.io.File import java.nio.file.Files import java.nio.file.Path -import java.nio.file.Paths fun writeSppfToDot(sppfNode: ISppfNode, filePath: String, label: String = "") { val queue: ArrayDeque = ArrayDeque(listOf(sppfNode)) diff --git a/test-shared/src/main/kotlin/org/ucfs/IDynamicGllTest.kt b/test-shared/src/main/kotlin/org/ucfs/IDynamicGllTest.kt index be2bbcd91..042541ebb 100644 --- a/test-shared/src/main/kotlin/org/ucfs/IDynamicGllTest.kt +++ b/test-shared/src/main/kotlin/org/ucfs/IDynamicGllTest.kt @@ -1,5 +1,6 @@ package org.ucfs +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.DynamicContainer import org.junit.jupiter.api.DynamicNode import org.junit.jupiter.api.TestFactory diff --git a/test-shared/src/test/kotlin/solver/GllRsmTest.kt b/test-shared/src/test/kotlin/solver/GllRsmTest.kt index 42e85385b..0804a9c3f 100644 --- a/test-shared/src/test/kotlin/solver/GllRsmTest.kt +++ b/test-shared/src/test/kotlin/solver/GllRsmTest.kt @@ -1,9 +1,8 @@ package solver -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.DynamicNode -import org.junit.jupiter.api.DynamicTest +import org.junit.jupiter.api.* import org.ucfs.IDynamicGllTest +import org.ucfs.IDynamicGllTest.Companion.GRAMMAR_FOLDER import org.ucfs.IDynamicGllTest.Companion.ONE_LINE_ERRORS_INPUTS import org.ucfs.IDynamicGllTest.Companion.ONE_LINE_INPUTS import org.ucfs.IDynamicGllTest.Companion.getFile @@ -15,6 +14,9 @@ import org.ucfs.parser.Gll import org.ucfs.parser.IGll import org.ucfs.rsm.RsmState import org.ucfs.rsm.readRsmFromTxt +import org.ucfs.rsm.writeRsmToDot +import org.ucfs.sppf.writeSppfToDot +import parser.generated.ScanerlessGrammarDsl import java.io.File import kotlin.test.assertNotNull @@ -24,6 +26,24 @@ class GllRsmTest : IDynamicGllTest { get() = "grammar.rsm" + @Test +// @Disabled + fun testSingle() { +// val folderName = "ab" +// val input = "a b" + + val folderName = "ambiguous" + val input = "a a a" + val folder = File(GRAMMAR_FOLDER).toPath().resolve(folderName).toFile() + val rsm = ScanerlessGrammarDsl().rsm + + val gll = getGll(input, rsm) + val result = gll.parse().first + assertNotNull(result) + writeSppfToDot(result, "boob.dot") + writeRsmToDot(rsm, "rsm.dot") + } + private fun getGll(input: String, rsm: RsmState): Gll { return Gll.gll(rsm, LinearInput.buildFromString(input)) } diff --git a/test-shared/src/test/resources/grammars/ambiguous/grammar.rsm b/test-shared/src/test/resources/grammars/ambiguous/grammar.rsm index e4aa851e3..9a249217f 100644 --- a/test-shared/src/test/resources/grammars/ambiguous/grammar.rsm +++ b/test-shared/src/test/resources/grammars/ambiguous/grammar.rsm @@ -1,10 +1,12 @@ -StartState(id=0,nonterminal=Nonterminal("S"),isStart=true,isFinal=false) +StartState(id=10,nonterminal=Nonterminal("S1"),isStart=true,isFinal=false) +State(id=10,nonterminal=Nonterminal("S1"),isStart=true,isFinal=false) +State(id=11,nonterminal=Nonterminal("S1"),isStart=true,isFinal=false) State(id=0,nonterminal=Nonterminal("S"),isStart=true,isFinal=false) -State(id=1,nonterminal=Nonterminal("S"),isStart=false,isFinal=true) +State(id=1,nonterminal=Nonterminal("S"),isStart=false,isFinal=false) State(id=2,nonterminal=Nonterminal("S"),isStart=false,isFinal=true) -State(id=3,nonterminal=Nonterminal("S"),isStart=false,isFinal=true) -TerminalEdge(tail=0,head=3,terminal=Terminal("a")) +TerminalEdge(tail=0,head=2,terminal=Terminal("a")) +NonterminalEdge(tail=10,head=11,nonterminal=Nonterminal("S")) +NonterminalEdge(tail=0,head=1,nonterminal=Nonterminal("S")) NonterminalEdge(tail=0,head=1,nonterminal=Nonterminal("S")) NonterminalEdge(tail=1,head=2,nonterminal=Nonterminal("S")) -NonterminalEdge(tail=2,head=3,nonterminal=Nonterminal("S")) \ No newline at end of file