diff --git a/solver/src/main/kotlin/org/ucfs/descriptors/DescriptorsStorage.kt b/solver/src/main/kotlin/org/ucfs/descriptors/DescriptorsStorage.kt index a4ad244a1..4e79bb00c 100644 --- a/solver/src/main/kotlin/org/ucfs/descriptors/DescriptorsStorage.kt +++ b/solver/src/main/kotlin/org/ucfs/descriptors/DescriptorsStorage.kt @@ -6,22 +6,16 @@ import org.ucfs.parser.ParsingException * Collection of default descriptors * @param VertexType - type of vertex in input graph */ -open class DescriptorsStorage{ +open class DescriptorsStorage { /** * Collection of already handled descriptors, accessible via descriptor's hashcode */ - private val handledDescriptors = ArrayList>() + private val handledDescriptors = HashSet>() private val descriptorsToHandle = ArrayDeque>() private fun isEmpty() = descriptorsToHandle.isEmpty() - private fun addToHandling(descriptor: Descriptor) { - if (!isAlreadyHandled(descriptor)) { - descriptorsToHandle.addLast(descriptor) - } - } - /** * @return next default descriptor to handle */ @@ -32,23 +26,13 @@ open class DescriptorsStorage{ return descriptorsToHandle.removeLast() } - /** - * @param descriptor - descriptor to check - * @return true if the descriptor was already processed, false otherwise - */ - private fun isAlreadyHandled(descriptor: Descriptor): Boolean { - val handledDescriptor = handledDescriptors.find { descriptor.hashCode() == it.hashCode() } - - return handledDescriptor != null - } - fun addToHandled(descriptor: Descriptor) { handledDescriptors.add(descriptor) } fun add(descriptor: Descriptor) { - if(!isAlreadyHandled(descriptor)){ - addToHandling(descriptor) + if(!handledDescriptors.contains(descriptor)){ + descriptorsToHandle.addLast(descriptor) } } /** diff --git a/solver/src/main/kotlin/org/ucfs/gss/GraphStructuredStack.kt b/solver/src/main/kotlin/org/ucfs/gss/GraphStructuredStack.kt index 14d06b529..db0a9abcf 100644 --- a/solver/src/main/kotlin/org/ucfs/gss/GraphStructuredStack.kt +++ b/solver/src/main/kotlin/org/ucfs/gss/GraphStructuredStack.kt @@ -5,15 +5,11 @@ import org.ucfs.rsm.RsmState import org.ucfs.sppf.node.RangeSppfNode class GraphStructuredStack { - val nodes = ArrayList>() + val nodes = HashMap, GssNode>() fun getOrCreateNode(input: InputNode, rsm: RsmState): GssNode { - val node = findNode(input, rsm) - return if (node == null) GssNode(rsm, input) else node - } - - fun findNode(input: InputNode, rsm: RsmState): GssNode? { - return nodes.find { node -> node.inputPosition == input && node.rsm == rsm } + val node = GssNode(rsm, input) + return nodes.getOrPut(node, {node}) } fun addEdge( diff --git a/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt b/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt index ed6da5e5e..c0817b4a7 100644 --- a/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt +++ b/solver/src/main/kotlin/org/ucfs/gss/GssNode.kt @@ -1,6 +1,5 @@ package org.ucfs.gss -import org.ucfs.descriptors.Descriptor import org.ucfs.rsm.RsmState import org.ucfs.sppf.node.RangeSppfNode import java.util.* @@ -20,9 +19,10 @@ data class GssNode( /** * Pointer to vertex in input graph */ - val inputPosition: InputNodeType, val id: Int = lastId++ + val inputPosition: InputNodeType, ) { + val id: Int = lastId++ val popped = ArrayList>() val outgoingEdges = ArrayList>() @@ -32,7 +32,6 @@ data class GssNode( */ fun addEdge(edge: GssEdge): ArrayList> { outgoingEdges.add(edge) - //TODO return popped } diff --git a/solver/src/main/kotlin/org/ucfs/parser/Gll.kt b/solver/src/main/kotlin/org/ucfs/parser/Gll.kt index 722e3d9ac..6359a3f59 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/Gll.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/Gll.kt @@ -42,21 +42,16 @@ class Gll private constructor( descriptor.rsmState, descriptor.rsmState, ) - val range = ctx.sppfStorage.addNode(RangeSppfNode(input, rsm, Range)) - val epsilon = ctx.sppfStorage.addNode( - RangeSppfNode(input, rsm, EpsilonNonterminalType(descriptor.gssNode.rsm)) - ) - range.children.add(epsilon) - return range + return ctx.sppfStorage.addEpsilonNode(input, rsm, descriptor.gssNode.rsm) } private fun handlePoppedGssEdge( poppedGssEdge: GssEdge, descriptor: Descriptor, childSppf: RangeSppfNode ) { val leftRange = poppedGssEdge.matchedRange - val startRsmState = if (poppedGssEdge.matchedRange.type == EmptyType) poppedGssEdge.gssNode.rsm + val startRsmState = if (poppedGssEdge.matchedRange.type is EmptyType) poppedGssEdge.gssNode.rsm else poppedGssEdge.matchedRange.rsmRange!!.to - val rightRange = ctx.sppfStorage.addNode( + val rightRange = ctx.sppfStorage.addNonterminalNode( InputRange( descriptor.gssNode.inputPosition, descriptor.inputPosition ), RsmRange( @@ -64,8 +59,7 @@ class Gll private constructor( poppedGssEdge.state, ), descriptor.gssNode.rsm, childSppf ) - ctx.sppfStorage.addNode(rightRange) - val newRange = ctx.sppfStorage.addNode(leftRange, rightRange) + val newRange = ctx.sppfStorage.addIntermediateNode(leftRange, rightRange) val newDescriptor = Descriptor( descriptor.inputPosition, poppedGssEdge.gssNode, poppedGssEdge.state, newRange ) @@ -79,8 +73,14 @@ class Gll private constructor( override fun handleDescriptor(descriptor: Descriptor) { ctx.descriptors.addToHandled(descriptor) if (descriptor.rsmState.isFinal) { - val matchedRange = if (descriptor.sppfNode.type == EmptyType) { - getEpsilonRange(descriptor) + val matchedRange = if (descriptor.sppfNode.type is EmptyType) { + val node = getEpsilonRange(descriptor) + //TODO fix + // dirty hack: in fact it's equivavelnt descriptors + // but only initial was added in handlet set + ctx.descriptors.addToHandled(Descriptor(descriptor.inputPosition, + descriptor.gssNode, descriptor.rsmState, node)) + node } else { 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 1b156b726..fd7576418 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/IGll.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/IGll.kt @@ -75,14 +75,13 @@ interface IGll { for (rangeToPop in positionToPops) { val leftSubRange = descriptor.sppfNode - val rightSubRange = ctx.sppfStorage.addNode( - RangeSppfNode( - rangeToPop.inputRange, RsmRange( + val rightSubRange = ctx.sppfStorage.addNonterminalNode( + rangeToPop.inputRange!!, RsmRange( descriptor.rsmState, destinationRsmState - ), NonterminalType(rsmStartState) + ), rsmStartState ) - ) - val newSppfNode = ctx.sppfStorage.addNode(leftSubRange, rightSubRange) + + val newSppfNode = ctx.sppfStorage.addIntermediateNode(leftSubRange, rightSubRange) //TODO why these parameters??? newDescriptor = Descriptor( @@ -108,7 +107,7 @@ interface IGll { destinationRsmState, ), terminal ) - val intermediateOrTerminalSppf = ctx.sppfStorage.addNode(descriptor.sppfNode, terminalSppfNode) + val intermediateOrTerminalSppf = ctx.sppfStorage.addIntermediateNode(descriptor.sppfNode, terminalSppfNode) val descriptorForTerminal = Descriptor( inputEdge.targetVertex, descriptor.gssNode, destinationRsmState, intermediateOrTerminalSppf ) diff --git a/solver/src/main/kotlin/org/ucfs/sppf/SppfStorage.kt b/solver/src/main/kotlin/org/ucfs/sppf/SppfStorage.kt index 61b24598d..94194b664 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/SppfStorage.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/SppfStorage.kt @@ -14,17 +14,30 @@ open class SppfStorage { private val createdSppfNodes: HashMap, RangeSppfNode> = HashMap() - fun addNode(node: RangeSppfNode): RangeSppfNode { + private fun addNode(node: RangeSppfNode): RangeSppfNode { return createdSppfNodes.getOrPut(node, { node }) } /** * Add nonterminal node after pop */ - fun addNode( - input: InputRange, rsm: RsmRange, startState: RsmState, childSppf: RangeSppfNode + fun addNonterminalNode( + input: InputRange, + rsm: RsmRange, + startState: RsmState, + childSppf: RangeSppfNode? = null + ): RangeSppfNode { + return if (childSppf == null) addNode(input, rsm, NonterminalType(startState)) + else addNode(input, rsm, NonterminalType(startState), listOf(childSppf)) + } + + fun addEpsilonNode( + input: InputRange, + rsmRange: RsmRange, + rsmState: RsmState ): RangeSppfNode { - return addNode(input, rsm, NonterminalType(startState), listOf(childSppf)) + return addNode( + input, rsmRange, EpsilonNonterminalType(rsmState)) } /** @@ -36,11 +49,11 @@ open class SppfStorage { return addNode(input, rsm, TerminalType(terminal)) } - fun addNode( + fun addIntermediateNode( leftSubtree: RangeSppfNode, rightSubtree: RangeSppfNode ): RangeSppfNode { - if (leftSubtree.type == EmptyType) { + if (leftSubtree.type is EmptyType) { return rightSubtree } return addNode( @@ -66,7 +79,11 @@ open class SppfStorage { if (!rangeNode.children.contains(valueNode)) { rangeNode.children.add(valueNode) } - valueNode.children.addAll(children) + for(child in children){ + if (!valueNode.children.contains(child)){ + valueNode.children.add(child) + } + } return rangeNode } } \ No newline at end of file diff --git a/solver/src/main/kotlin/org/ucfs/sppf/node/RangeSppfNode.kt b/solver/src/main/kotlin/org/ucfs/sppf/node/RangeSppfNode.kt index 6d6294c34..93745a17a 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/node/RangeSppfNode.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/node/RangeSppfNode.kt @@ -26,7 +26,7 @@ data class RangeSppfNode( val children = ArrayList>() } -fun getEmptyRange(): RangeSppfNode = RangeSppfNode(null, null, EmptyType) +fun getEmptyRange(): RangeSppfNode = RangeSppfNode(null, null, EmptyType()) data class InputRange( val from: VertexType, @@ -39,10 +39,10 @@ data class RsmRange( ) interface RangeType - +var lastEmptyId = 0 object Range : RangeType data class TerminalType(val terminal: T) : RangeType data class NonterminalType(val startState: RsmState) : RangeType data class EpsilonNonterminalType(val startState: RsmState) : RangeType data class IntermediateType(val grammarSlot: RsmState, val inputPosition: VertexType) : RangeType -object EmptyType : RangeType +data class EmptyType(private val id: Int = lastEmptyId++) : RangeType diff --git a/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt b/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt index ab358363a..c45bc0ffe 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt @@ -16,49 +16,54 @@ fun writeSppfToDot(sppfNode: RangeSppfNode, filePath: Str fun getSppfDot(sppfNode: RangeSppfNode, label: String = ""): String { val queue: ArrayDeque> = ArrayDeque(listOf(sppfNode)) - val edges: HashMap, HashSet>> = HashMap() val visited: HashSet = HashSet() var node: RangeSppfNode val sb = StringBuilder() sb.appendLine("digraph g {") sb.appendLine("labelloc=\"t\"") sb.appendLine("label=\"$label\"") - var nextNodeId = 0 val nodeViews = HashMap, String>() while (queue.isNotEmpty()) { node = queue.removeFirst() if (!visited.add(node.hashCode())) continue - nodeViews[node] = getNodeView(node) + nodeViews[node] = getNodeView(node, ) node.children.forEach { queue.addLast(it) - edges.getOrPut(node, { HashSet() }).add(it) } } val sortedViews = nodeViews.values.sorted() val nodeIds = HashMap, Int>() + val nodeById = HashMap>() for ((node, view) in nodeViews) { - nodeIds[node] = sortedViews.indexOf(view) + val id = sortedViews.indexOf(view) + nodeIds[node] = id + nodeById[id] = node } + for (i in sortedViews.indices) { sb.appendLine("$i ${sortedViews[i]}") } - val sortedEdges = ArrayList() - for ((head, tails) in edges) { - for (tail in tails) { - sortedEdges.add("${nodeIds[head]}->${nodeIds[tail]}") + for (i in nodeById.keys) { + val node = nodeById[i] + for(child in node!!.children) { + sb.appendLine("${nodeIds[node]}->${nodeIds[child]}") } + // if(node.children.size < 2){ + // continue + // } + // val cs = node.children.map({nodeIds[it]}).joinToString("->") + // sb.appendLine("{ rank = same; $cs [style=invis]}") } - for (edge in sortedEdges.sorted()) { - sb.appendLine(edge) - } + sb.appendLine("}") return sb.toString() } + enum class NodeShape(val view: String) { Terminal("rectangle"), Nonterminal("invtrapezium"), Intermediate("plain"), Empty("ellipse"), Range("ellipse"), Epsilon( "invhouse" @@ -66,51 +71,51 @@ enum class NodeShape(val view: String) { } fun fillNodeTemplate( - nodeInfo: String, inputRange: InputRange<*>?, shape: NodeShape, rsmRange: RsmRange? = null + id: String? = null, nodeInfo: String, inputRange: InputRange<*>?, shape: NodeShape, rsmRange: RsmRange? = null ): String { val inputRangeView = if (inputRange != null) "input: [${inputRange.from}, ${inputRange.to}]" else null val rsmRangeView = if (rsmRange != null) "rsm: [${rsmRange.from.id}, ${rsmRange.to.id}]" else null val view = listOfNotNull(nodeInfo, inputRangeView, rsmRangeView).joinToString(", ") - return "[label = \"${shape.name} $view\", shape = ${shape.view}]" + return "[label = \"${id?: ""}${shape.name} $view\", shape = ${shape.view}]" } -fun getNodeView(node: RangeSppfNode): String { +fun getNodeView(node: RangeSppfNode, id: String? = null): String { val type = node.type return when (type) { is TerminalType<*> -> { fillNodeTemplate( - "'${type.terminal}'", node.inputRange, NodeShape.Terminal + id, "'${type.terminal}'", node.inputRange, NodeShape.Terminal ) } is NonterminalType -> { fillNodeTemplate( - "${type.startState.nonterminal.name}", node.inputRange, NodeShape.Nonterminal + id, "${type.startState.nonterminal.name}", node.inputRange, NodeShape.Nonterminal ) } is IntermediateType<*> -> { fillNodeTemplate( - "input: ${type.inputPosition}, rsm: ${type.grammarSlot.id}", null, NodeShape.Intermediate + id, "input: ${type.inputPosition}, rsm: ${type.grammarSlot.id}", node.inputRange, NodeShape.Intermediate ) } is EmptyType -> { fillNodeTemplate( - "", null, NodeShape.Empty + id, "", null, NodeShape.Empty ) } is EpsilonNonterminalType -> { fillNodeTemplate( - "RSM: ${type.startState.id}", node.inputRange, NodeShape.Epsilon + id, "RSM: ${type.startState.id}", node.inputRange, NodeShape.Epsilon ) } is RangeType -> { fillNodeTemplate( - "", node.inputRange, NodeShape.Range, node.rsmRange + id, "", node.inputRange, NodeShape.Range, node.rsmRange ) } diff --git a/test-shared/src/test/kotlin/grammars/SimpleDyck.kt b/test-shared/src/test/kotlin/grammars/SimpleDyck.kt index 51b6104e4..8ff570101 100644 --- a/test-shared/src/test/kotlin/grammars/SimpleDyck.kt +++ b/test-shared/src/test/kotlin/grammars/SimpleDyck.kt @@ -18,7 +18,7 @@ class LoopDyck : Grammar() { val S by Nt().asStart() init { - S /= Option("(" * S * ")") + S /= Many( "(" * S * ")") } } diff --git a/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt b/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt index 43b728486..7eee2f4f8 100644 --- a/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt +++ b/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt @@ -13,9 +13,8 @@ abstract class AbstractCorrectnessTest { abstract fun getRootDataFolder(): Path - val grammars = listOf(SimplifiedDyck(), ABGrammar(), SALang(), Epsilon()) - //val grammars = listOf(LoopDyck()) - + val grammars = listOf(SimplifiedDyck(), ABGrammar(), SALang(), Epsilon(), LoopDyck()) + val regenerate = false //@TestFactory //TODO make it abstract by used grammar @Test diff --git a/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt b/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt index 3fac03f48..7f4fd1ded 100644 --- a/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt +++ b/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt @@ -22,7 +22,7 @@ class TreeCorrectnessTest : AbstractCorrectnessTest() { val input = inputFile.readText() val expectedResult = expectedFile.readText() val actualResult = runTest(input, grammar) - if (expectedResult.isEmpty()) { + if (expectedResult.isEmpty() || regenerate) { expectedFile.writeText(actualResult) } else { assertEquals(expectedResult, actualResult) diff --git a/test-shared/src/test/resources/correctness/tree/ABGrammar/ambig/result.dot b/test-shared/src/test/resources/correctness/tree/ABGrammar/ambig/result.dot index 8f45278aa..1d27629f1 100644 --- a/test-shared/src/test/resources/correctness/tree/ABGrammar/ambig/result.dot +++ b/test-shared/src/test/resources/correctness/tree/ABGrammar/ambig/result.dot @@ -15,6 +15,6 @@ label="" 3->7 4->2 5->7 -6->0 6->1 +6->0 } diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/linear/result.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/linear/result.dot deleted file mode 100644 index 57fd89a37..000000000 --- a/test-shared/src/test/resources/correctness/tree/LoopDyck/linear/result.dot +++ /dev/null @@ -1,27 +0,0 @@ -digraph g { -labelloc="t" -label="" -0 [label = "Epsilon RSM: S_0, input: [1, 1]", shape = invhouse] -1 [label = "Intermediate input: 1, rsm: S_1", shape = plain] -2 [label = "Intermediate input: 1, rsm: S_2", shape = plain] -3 [label = "Nonterminal S, input: [1, 1]", shape = invtrapezium] -4 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] -5 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] -6 [label = "Range , input: [0, 2], rsm: [S_0, S_3]", shape = ellipse] -7 [label = "Range , input: [1, 1], rsm: [S_0, S_0]", shape = ellipse] -8 [label = "Range , input: [1, 1], rsm: [S_1, S_2]", shape = ellipse] -9 [label = "Range , input: [1, 2], rsm: [S_2, S_3]", shape = ellipse] -10 [label = "Terminal '(', input: [0, 1]", shape = rectangle] -11 [label = "Terminal ')', input: [1, 2]", shape = rectangle] -1->4 -1->8 -2->5 -2->9 -3->7 -4->10 -5->1 -6->2 -7->0 -8->3 -9->11 -} diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/minimalWorstCase/input.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/minimalWorstCase/input.dot new file mode 100644 index 000000000..7c08420c5 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/minimalWorstCase/input.dot @@ -0,0 +1,7 @@ +digraph Input { + label="Minimal worst case, simple loop RSM for Dyck language" + start -> 0; + 0 -> 0 [label = "("]; + 0 -> 1 [label = ")"]; + 1 -> 0 [label = ")"]; +} \ No newline at end of file diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/minimalWorstCase/result.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/minimalWorstCase/result.dot new file mode 100644 index 000000000..8e702aee9 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/minimalWorstCase/result.dot @@ -0,0 +1,43 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Epsilon RSM: S_0, input: [0, 0]", shape = invhouse] +1 [label = "Intermediate input: 0, rsm: S_1, input: [0, 0]", shape = plain] +2 [label = "Intermediate input: 0, rsm: S_1, input: [0, 1]", shape = plain] +3 [label = "Intermediate input: 0, rsm: S_2, input: [0, 1]", shape = plain] +4 [label = "Intermediate input: 1, rsm: S_2, input: [0, 0]", shape = plain] +5 [label = "Nonterminal S, input: [0, 0]", shape = invtrapezium] +6 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +7 [label = "Range , input: [0, 0], rsm: [S_0, S_0]", shape = ellipse] +8 [label = "Range , input: [0, 0], rsm: [S_0, S_1]", shape = ellipse] +9 [label = "Range , input: [0, 0], rsm: [S_0, S_2]", shape = ellipse] +10 [label = "Range , input: [0, 0], rsm: [S_1, S_2]", shape = ellipse] +11 [label = "Range , input: [0, 1], rsm: [S_0, S_0]", shape = ellipse] +12 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +13 [label = "Range , input: [0, 1], rsm: [S_1, S_2]", shape = ellipse] +14 [label = "Range , input: [0, 1], rsm: [S_2, S_0]", shape = ellipse] +15 [label = "Range , input: [1, 0], rsm: [S_2, S_0]", shape = ellipse] +16 [label = "Terminal '(', input: [0, 0]", shape = rectangle] +17 [label = "Terminal ')', input: [0, 1]", shape = rectangle] +18 [label = "Terminal ')', input: [1, 0]", shape = rectangle] +1->8 +1->10 +2->8 +2->13 +3->9 +3->14 +4->12 +4->15 +5->7 +6->11 +7->0 +7->4 +8->16 +9->1 +10->5 +11->3 +12->2 +13->6 +14->17 +15->18 +} diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/linear/input.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/input.dot similarity index 50% rename from test-shared/src/test/resources/correctness/tree/LoopDyck/linear/input.dot rename to test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/input.dot index 2ce933246..21edd13ff 100644 --- a/test-shared/src/test/resources/correctness/tree/LoopDyck/linear/input.dot +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/input.dot @@ -1,4 +1,5 @@ digraph Input { + label="Two loops with common vertex, simple loop RSM for Dyck language" start -> 0; 0 -> 0 [label = "("]; 0 -> 0 [label = ")"]; diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/result.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/result.dot new file mode 100644 index 000000000..2f93dc957 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/result.dot @@ -0,0 +1,26 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Epsilon RSM: S_0, input: [0, 0]", shape = invhouse] +1 [label = "Intermediate input: 0, rsm: S_1, input: [0, 0]", shape = plain] +2 [label = "Intermediate input: 0, rsm: S_2, input: [0, 0]", shape = plain] +3 [label = "Nonterminal S, input: [0, 0]", shape = invtrapezium] +4 [label = "Range , input: [0, 0], rsm: [S_0, S_0]", shape = ellipse] +5 [label = "Range , input: [0, 0], rsm: [S_0, S_1]", shape = ellipse] +6 [label = "Range , input: [0, 0], rsm: [S_0, S_2]", shape = ellipse] +7 [label = "Range , input: [0, 0], rsm: [S_1, S_2]", shape = ellipse] +8 [label = "Range , input: [0, 0], rsm: [S_2, S_0]", shape = ellipse] +9 [label = "Terminal '(', input: [0, 0]", shape = rectangle] +10 [label = "Terminal ')', input: [0, 0]", shape = rectangle] +1->5 +1->7 +2->6 +2->8 +3->4 +4->0 +4->2 +5->9 +6->1 +7->3 +8->10 +} diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/input.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/input.dot new file mode 100644 index 000000000..2a79063bc --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/input.dot @@ -0,0 +1,10 @@ +digraph Input { + label="Second worst case, simple loop RSM for Dyck language" + start -> 0; + 0 -> 1 [label = ")"]; + 1 -> 2 [label = ")"]; + 2 -> 0 [label = ")"]; + + 0 -> 3 [label = "("]; + 3 -> 0 [label = "("]; +} \ No newline at end of file diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/result.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/result.dot new file mode 100644 index 000000000..130fa1bc3 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/result.dot @@ -0,0 +1,122 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Epsilon RSM: S_0, input: [0, 0]", shape = invhouse] +1 [label = "Intermediate input: 0, rsm: S_0, input: [3, 3]", shape = plain] +2 [label = "Intermediate input: 0, rsm: S_1, input: [3, 0]", shape = plain] +3 [label = "Intermediate input: 0, rsm: S_1, input: [3, 1]", shape = plain] +4 [label = "Intermediate input: 0, rsm: S_1, input: [3, 2]", shape = plain] +5 [label = "Intermediate input: 0, rsm: S_2, input: [0, 1]", shape = plain] +6 [label = "Intermediate input: 0, rsm: S_2, input: [3, 1]", shape = plain] +7 [label = "Intermediate input: 1, rsm: S_2, input: [0, 2]", shape = plain] +8 [label = "Intermediate input: 1, rsm: S_2, input: [3, 2]", shape = plain] +9 [label = "Intermediate input: 2, rsm: S_2, input: [0, 0]", shape = plain] +10 [label = "Intermediate input: 2, rsm: S_2, input: [3, 0]", shape = plain] +11 [label = "Intermediate input: 3, rsm: S_1, input: [0, 0]", shape = plain] +12 [label = "Intermediate input: 3, rsm: S_1, input: [0, 1]", shape = plain] +13 [label = "Intermediate input: 3, rsm: S_1, input: [0, 2]", shape = plain] +14 [label = "Intermediate input: 3, rsm: S_1, input: [3, 0]", shape = plain] +15 [label = "Intermediate input: 3, rsm: S_1, input: [3, 1]", shape = plain] +16 [label = "Intermediate input: 3, rsm: S_1, input: [3, 2]", shape = plain] +17 [label = "Nonterminal S, input: [0, 0]", shape = invtrapezium] +18 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +19 [label = "Nonterminal S, input: [0, 2]", shape = invtrapezium] +20 [label = "Nonterminal S, input: [3, 0]", shape = invtrapezium] +21 [label = "Nonterminal S, input: [3, 1]", shape = invtrapezium] +22 [label = "Nonterminal S, input: [3, 2]", shape = invtrapezium] +23 [label = "Range , input: [0, 0], rsm: [S_0, S_0]", shape = ellipse] +24 [label = "Range , input: [0, 0], rsm: [S_0, S_2]", shape = ellipse] +25 [label = "Range , input: [0, 0], rsm: [S_1, S_2]", shape = ellipse] +26 [label = "Range , input: [0, 1], rsm: [S_0, S_0]", shape = ellipse] +27 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +28 [label = "Range , input: [0, 1], rsm: [S_1, S_2]", shape = ellipse] +29 [label = "Range , input: [0, 1], rsm: [S_2, S_0]", shape = ellipse] +30 [label = "Range , input: [0, 2], rsm: [S_0, S_0]", shape = ellipse] +31 [label = "Range , input: [0, 2], rsm: [S_0, S_2]", shape = ellipse] +32 [label = "Range , input: [0, 2], rsm: [S_1, S_2]", shape = ellipse] +33 [label = "Range , input: [0, 3], rsm: [S_0, S_1]", shape = ellipse] +34 [label = "Range , input: [1, 2], rsm: [S_2, S_0]", shape = ellipse] +35 [label = "Range , input: [2, 0], rsm: [S_2, S_0]", shape = ellipse] +36 [label = "Range , input: [3, 0], rsm: [S_0, S_0]", shape = ellipse] +37 [label = "Range , input: [3, 0], rsm: [S_0, S_1]", shape = ellipse] +38 [label = "Range , input: [3, 0], rsm: [S_0, S_2]", shape = ellipse] +39 [label = "Range , input: [3, 0], rsm: [S_1, S_2]", shape = ellipse] +40 [label = "Range , input: [3, 1], rsm: [S_0, S_0]", shape = ellipse] +41 [label = "Range , input: [3, 1], rsm: [S_0, S_2]", shape = ellipse] +42 [label = "Range , input: [3, 1], rsm: [S_1, S_2]", shape = ellipse] +43 [label = "Range , input: [3, 2], rsm: [S_0, S_0]", shape = ellipse] +44 [label = "Range , input: [3, 2], rsm: [S_0, S_2]", shape = ellipse] +45 [label = "Range , input: [3, 2], rsm: [S_1, S_2]", shape = ellipse] +46 [label = "Range , input: [3, 3], rsm: [S_0, S_1]", shape = ellipse] +47 [label = "Terminal '(', input: [0, 3]", shape = rectangle] +48 [label = "Terminal '(', input: [3, 0]", shape = rectangle] +49 [label = "Terminal ')', input: [0, 1]", shape = rectangle] +50 [label = "Terminal ')', input: [1, 2]", shape = rectangle] +51 [label = "Terminal ')', input: [2, 0]", shape = rectangle] +1->36 +1->33 +2->37 +2->25 +3->37 +3->28 +4->37 +4->32 +5->24 +5->29 +6->38 +6->29 +7->27 +7->34 +8->41 +8->34 +9->31 +9->35 +10->44 +10->35 +11->33 +11->39 +12->33 +12->42 +13->33 +13->45 +14->46 +14->39 +15->46 +15->42 +16->46 +16->45 +17->23 +18->26 +19->30 +20->36 +21->40 +22->43 +23->0 +23->9 +24->11 +25->17 +26->5 +27->12 +28->18 +29->49 +30->7 +31->13 +32->19 +33->47 +34->50 +35->51 +36->10 +37->48 +38->2 +38->14 +39->20 +40->6 +41->15 +41->3 +42->21 +43->8 +44->4 +44->16 +45->22 +46->1 +} diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/input.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/input.dot new file mode 100644 index 000000000..385ff2cdb --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/input.dot @@ -0,0 +1,8 @@ +digraph Input { + label="Two concatenated linear pairs of brackets, simple loop RSM for Dyck language" + start -> 0; + 0 -> 1 [label = "("]; + 1 -> 2 [label = ")"]; + 2 -> 3 [label = "("]; + 3 -> 4 [label = ")"]; +} \ No newline at end of file diff --git a/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/result.dot b/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/result.dot new file mode 100644 index 000000000..ec8facdb3 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/result.dot @@ -0,0 +1,55 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Epsilon RSM: S_0, input: [1, 1]", shape = invhouse] +1 [label = "Epsilon RSM: S_0, input: [3, 3]", shape = invhouse] +2 [label = "Intermediate input: 1, rsm: S_1, input: [0, 1]", shape = plain] +3 [label = "Intermediate input: 1, rsm: S_2, input: [0, 2]", shape = plain] +4 [label = "Intermediate input: 2, rsm: S_0, input: [0, 3]", shape = plain] +5 [label = "Intermediate input: 3, rsm: S_1, input: [0, 3]", shape = plain] +6 [label = "Intermediate input: 3, rsm: S_2, input: [0, 4]", shape = plain] +7 [label = "Nonterminal S, input: [1, 1]", shape = invtrapezium] +8 [label = "Nonterminal S, input: [3, 3]", shape = invtrapezium] +9 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +10 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +11 [label = "Range , input: [0, 2], rsm: [S_0, S_0]", shape = ellipse] +12 [label = "Range , input: [0, 3], rsm: [S_0, S_1]", shape = ellipse] +13 [label = "Range , input: [0, 3], rsm: [S_0, S_2]", shape = ellipse] +14 [label = "Range , input: [0, 4], rsm: [S_0, S_0]", shape = ellipse] +15 [label = "Range , input: [1, 1], rsm: [S_0, S_0]", shape = ellipse] +16 [label = "Range , input: [1, 1], rsm: [S_1, S_2]", shape = ellipse] +17 [label = "Range , input: [1, 2], rsm: [S_2, S_0]", shape = ellipse] +18 [label = "Range , input: [2, 3], rsm: [S_0, S_1]", shape = ellipse] +19 [label = "Range , input: [3, 3], rsm: [S_0, S_0]", shape = ellipse] +20 [label = "Range , input: [3, 3], rsm: [S_1, S_2]", shape = ellipse] +21 [label = "Range , input: [3, 4], rsm: [S_2, S_0]", shape = ellipse] +22 [label = "Terminal '(', input: [0, 1]", shape = rectangle] +23 [label = "Terminal '(', input: [2, 3]", shape = rectangle] +24 [label = "Terminal ')', input: [1, 2]", shape = rectangle] +25 [label = "Terminal ')', input: [3, 4]", shape = rectangle] +2->9 +2->16 +3->10 +3->17 +4->11 +4->18 +5->12 +5->20 +6->13 +6->21 +7->15 +8->19 +9->22 +10->2 +11->3 +12->4 +13->5 +14->6 +15->0 +16->7 +17->24 +18->23 +19->1 +20->8 +21->25 +} diff --git a/test-shared/src/test/resources/correctness/tree/SALang/linear/result.dot b/test-shared/src/test/resources/correctness/tree/SALang/linear/result.dot index 056a94163..53b75dfe8 100644 --- a/test-shared/src/test/resources/correctness/tree/SALang/linear/result.dot +++ b/test-shared/src/test/resources/correctness/tree/SALang/linear/result.dot @@ -1,9 +1,9 @@ digraph g { labelloc="t" label="" -0 [label = "Intermediate input: 1, rsm: A_1", shape = plain] -1 [label = "Intermediate input: 1, rsm: S_2", shape = plain] -2 [label = "Intermediate input: 2, rsm: S_1", shape = plain] +0 [label = "Intermediate input: 1, rsm: A_1, input: [0, 2]", shape = plain] +1 [label = "Intermediate input: 1, rsm: S_2, input: [0, 2]", shape = plain] +2 [label = "Intermediate input: 2, rsm: S_1, input: [0, 3]", shape = plain] 3 [label = "Nonterminal A, input: [0, 2]", shape = invtrapezium] 4 [label = "Range , input: [0, 1], rsm: [A_0, A_1]", shape = ellipse] 5 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] @@ -18,18 +18,18 @@ label="" 14 [label = "Terminal 'c', input: [2, 3]", shape = rectangle] 0->4 0->9 -1->10 1->5 -10->13 -11->14 -2->11 +1->10 2->7 +2->11 3->6 4->12 5->12 6->0 -7->1 7->3 +7->1 8->2 9->13 +10->13 +11->14 } diff --git a/test-shared/src/test/resources/correctness/tree/SimplifiedDyck/linear/result.dot b/test-shared/src/test/resources/correctness/tree/SimplifiedDyck/linear/result.dot index 57fd89a37..851619986 100644 --- a/test-shared/src/test/resources/correctness/tree/SimplifiedDyck/linear/result.dot +++ b/test-shared/src/test/resources/correctness/tree/SimplifiedDyck/linear/result.dot @@ -2,8 +2,8 @@ digraph g { labelloc="t" label="" 0 [label = "Epsilon RSM: S_0, input: [1, 1]", shape = invhouse] -1 [label = "Intermediate input: 1, rsm: S_1", shape = plain] -2 [label = "Intermediate input: 1, rsm: S_2", shape = plain] +1 [label = "Intermediate input: 1, rsm: S_1, input: [0, 1]", shape = plain] +2 [label = "Intermediate input: 1, rsm: S_2, input: [0, 2]", shape = plain] 3 [label = "Nonterminal S, input: [1, 1]", shape = invtrapezium] 4 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] 5 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse]