diff --git a/solver/src/main/kotlin/org/ucfs/grammar/combinator/Grammar.kt b/solver/src/main/kotlin/org/ucfs/grammar/combinator/Grammar.kt index abc205a51..227491583 100644 --- a/solver/src/main/kotlin/org/ucfs/grammar/combinator/Grammar.kt +++ b/solver/src/main/kotlin/org/ucfs/grammar/combinator/Grammar.kt @@ -12,6 +12,7 @@ open class Grammar { val nonTerms = ArrayList() private lateinit var startNt: Nt + private lateinit var fictitiousStartNt: Nt private var _rsm: RsmState? = null val rsm: RsmState @@ -22,12 +23,6 @@ open class Grammar { return _rsm!! } - fun setStart(expr: Regexp) { - if (expr is Nt) { - startNt = expr - } else throw IllegalArgumentException("Only NT object can be start state for Grammar") - } - fun Nt.asStart(): Nt { if (this@Grammar::startNt.isInitialized) { throw Exception("Nonterminal ${nonterm.name} is already initialized") @@ -43,6 +38,8 @@ open class Grammar { private fun buildRsm(): RsmState { nonTerms.forEach { it.buildRsmBox() } //if nonterminal not initialized -- it will be checked in buildRsmBox() - return startNt.nonterm.startState + fictitiousStartNt = Nt(startNt, "fictiveStart") + fictitiousStartNt.buildRsmBox() + return fictitiousStartNt.nonterm.startState } } diff --git a/solver/src/main/kotlin/org/ucfs/grammar/combinator/regexp/Nt.kt b/solver/src/main/kotlin/org/ucfs/grammar/combinator/regexp/Nt.kt index a9d5f6949..6feb8aafe 100644 --- a/solver/src/main/kotlin/org/ucfs/grammar/combinator/regexp/Nt.kt +++ b/solver/src/main/kotlin/org/ucfs/grammar/combinator/regexp/Nt.kt @@ -10,6 +10,11 @@ open class Nt() : DerivedSymbol { constructor(lhs: Regexp) : this() { rsmDescription = lhs } + constructor(lhs: Regexp, name: String) : this() { + rsmDescription = lhs + this.nonterm = Nonterminal(name) + } + lateinit var nonterm: Nonterminal private set diff --git a/solver/src/main/kotlin/org/ucfs/parser/Gll.kt b/solver/src/main/kotlin/org/ucfs/parser/Gll.kt index 6359a3f59..022935439 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/Gll.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/Gll.kt @@ -29,7 +29,8 @@ class Gll private constructor( fun gll( startState: RsmState, inputGraph: IInputGraph ): Gll { - return Gll(Context(startState, inputGraph), IntersectionEngine) + val finalState = startState.outgoingEdges.get(0).destinationState + return Gll(Context(startState, finalState, inputGraph), IntersectionEngine) } } @@ -66,6 +67,11 @@ class Gll private constructor( ctx.descriptors.add(newDescriptor) } + fun isParseResult(descriptor: Descriptor, matchedRange: RangeSppfNode): Boolean { + return matchedRange.inputRange!!.from in ctx.input.getInputStartVertices() + && matchedRange.rsmRange!!.from == ctx.fictiveStartState + && matchedRange.rsmRange.to == ctx.fictiveFinalState + } /** * Processes descriptor * @param descriptor - descriptor to process @@ -77,7 +83,7 @@ class Gll private constructor( val node = getEpsilonRange(descriptor) //TODO fix // dirty hack: in fact it's equivavelnt descriptors - // but only initial was added in handlet set + // but only initial was added in handled set ctx.descriptors.addToHandled(Descriptor(descriptor.inputPosition, descriptor.gssNode, descriptor.rsmState, node)) node @@ -87,11 +93,14 @@ class Gll private constructor( for (poppedEdge in ctx.gss.pop(descriptor, matchedRange)) { handlePoppedGssEdge(poppedEdge, descriptor, matchedRange) } - if (descriptor.gssNode.outgoingEdges.isEmpty() && descriptor.gssNode.rsm.isStart) { - ctx.parseResult = matchedRange + if (isParseResult(descriptor, matchedRange)) { + + if(ctx.parseResult == null) { + ctx.parseResult = matchedRange + } + ctx.parseResults.add(matchedRange) } } - engine.handleEdges(this, descriptor) } } diff --git a/solver/src/main/kotlin/org/ucfs/parser/IGll.kt b/solver/src/main/kotlin/org/ucfs/parser/IGll.kt index fd7576418..6f05f55d1 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/IGll.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/IGll.kt @@ -36,7 +36,9 @@ interface IGll { curDescriptor = ctx.descriptors.nextToHandle() } - return ctx.parseResult + // assert(ctx.parseResult != null) + // assert(ctx.parseResult!!.children.size == 1) + return ctx.parseResult!!.children.get(0) } /** @@ -52,9 +54,9 @@ interface IGll { fun initDescriptors(input: IInputGraph) { for (startVertex in input.getInputStartVertices()) { - val gssNode = ctx.gss.getOrCreateNode(startVertex, ctx.startState) + val gssNode = ctx.gss.getOrCreateNode(startVertex, ctx.fictiveStartState) val startDescriptor = Descriptor( - startVertex, gssNode, ctx.startState, getEmptyRange() + startVertex, gssNode, ctx.fictiveStartState, getEmptyRange(true) ) ctx.descriptors.add(startDescriptor) } diff --git a/solver/src/main/kotlin/org/ucfs/parser/context/Context.kt b/solver/src/main/kotlin/org/ucfs/parser/context/Context.kt index a18eefef4..673d3114b 100644 --- a/solver/src/main/kotlin/org/ucfs/parser/context/Context.kt +++ b/solver/src/main/kotlin/org/ucfs/parser/context/Context.kt @@ -1,6 +1,5 @@ package org.ucfs.parser.context -import org.ucfs.descriptors.Descriptor import org.ucfs.descriptors.DescriptorsStorage import org.ucfs.gss.GraphStructuredStack import org.ucfs.input.IInputGraph @@ -18,7 +17,8 @@ class Context ( /** * Starting state of accepting Nonterminal in RSM */ - val startState: RsmState, + val fictiveStartState: RsmState, + val fictiveFinalState: RsmState, val input: IInputGraph @@ -37,4 +37,5 @@ class Context ( val gss: GraphStructuredStack = GraphStructuredStack() var parseResult: RangeSppfNode? = null + var parseResults = ArrayList>() } \ No newline at end of file diff --git a/solver/src/main/kotlin/org/ucfs/rsm/RsmWrite.kt b/solver/src/main/kotlin/org/ucfs/rsm/RsmWrite.kt index 0e36732e6..ec275bfbc 100644 --- a/solver/src/main/kotlin/org/ucfs/rsm/RsmWrite.kt +++ b/solver/src/main/kotlin/org/ucfs/rsm/RsmWrite.kt @@ -87,7 +87,7 @@ fun writeRsmToTxt(startState: RsmState, pathToTXT: String) { } fun writeRsmToDot(startState: RsmState, filePath: String) { - val states = getAllStates(startState) + val states = getAllStates((startState.outgoingEdges.get(0).symbol as Nonterminal).startState) val boxes: HashMap> = HashMap() for (state in states) { 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 93745a17a..1cb8ba0f8 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,13 @@ data class RangeSppfNode( val children = ArrayList>() } -fun getEmptyRange(): RangeSppfNode = RangeSppfNode(null, null, EmptyType()) +fun getEmptyRange(isStart: Boolean = false): RangeSppfNode { + val type = EmptyType() + if(isStart) { + type.isStart = isStart + } + return RangeSppfNode(null, null, type) +} data class InputRange( val from: VertexType, @@ -45,4 +51,16 @@ 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 -data class EmptyType(private val id: Int = lastEmptyId++) : RangeType +class EmptyType : RangeType { + var isStart = false + + @Override + override fun equals(other: Any?): Boolean { + return other is EmptyType + } + + @Override + override fun hashCode(): Int { + return 12 + } +} diff --git a/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt b/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt index c45bc0ffe..d80d93759 100644 --- a/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt +++ b/solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt @@ -27,7 +27,7 @@ fun getSppfDot(sppfNode: RangeSppfNode, label: String = " node = queue.removeFirst() if (!visited.add(node.hashCode())) continue - nodeViews[node] = getNodeView(node, ) + nodeViews[node] = getNodeView(node,)// node.id.toString()) node.children.forEach { queue.addLast(it) diff --git a/test-shared/src/test/kotlin/grammars/SimpleDyck.kt b/test-shared/src/test/kotlin/grammars/SimpleDyck.kt index 8ff570101..3cf9273dd 100644 --- a/test-shared/src/test/kotlin/grammars/SimpleDyck.kt +++ b/test-shared/src/test/kotlin/grammars/SimpleDyck.kt @@ -1,6 +1,7 @@ package grammars import org.ucfs.grammar.combinator.Grammar +import org.ucfs.grammar.combinator.extension.StringExtension.or import org.ucfs.grammar.combinator.extension.StringExtension.times import org.ucfs.grammar.combinator.regexp.* import org.ucfs.grammar.combinator.regexp.Epsilon @@ -11,6 +12,7 @@ class SimplifiedDyck : Grammar() { init { S /= Option("(" * S * ")") + // S = eps | ( S ) } } @@ -19,13 +21,14 @@ class LoopDyck : Grammar() { init { S /= Many( "(" * S * ")") + // S = [ ( S ) ]* } } class ABGrammar : Grammar() { - val A by Nt(Term("a")) + val A by Nt(Term("a")) // A -> a val C by Nt(Term("a")) - val B by Nt(C) + val B by Nt(C) // C -> B val S by Nt(A or B).asStart() } @@ -36,4 +39,32 @@ class SALang : Grammar() { class Epsilon : Grammar() { val S by Nt(Epsilon).asStart() +} + +/** + * Can parse only one symbol 'a' + */ +class AmbiguousAStar1: Grammar() { + val S by Nt().asStart() + + init { + S /= "a" or S + } +} + +class AmbiguousAStar2: Grammar() { + val S by Nt().asStart() + + init { + S /= "a" or S * S + } +} + + +class AmbiguousAStar3: Grammar() { + val S by Nt().asStart() + + init { + S /= "a" or S * S + } } \ No newline at end of file diff --git a/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt b/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt index 7eee2f4f8..eeb18d32a 100644 --- a/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt +++ b/test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt @@ -13,7 +13,9 @@ abstract class AbstractCorrectnessTest { abstract fun getRootDataFolder(): Path - val grammars = listOf(SimplifiedDyck(), ABGrammar(), SALang(), Epsilon(), LoopDyck()) + val grammars = listOf(SimplifiedDyck(), ABGrammar(), SALang(), Epsilon(), LoopDyck(), AmbiguousAStar2(), AmbiguousAStar1()) + //TODO return only one result for ambiguous AmbiguousAStar2(), AmbiguousAStar1() + // TODO fix worst case for loopdyck val regenerate = false //@TestFactory //TODO make it abstract by used grammar diff --git a/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt b/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt index 7f4fd1ded..6ead66b12 100644 --- a/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt +++ b/test-shared/src/test/kotlin/solver/TreeCorrectnessTest.kt @@ -25,7 +25,7 @@ class TreeCorrectnessTest : AbstractCorrectnessTest() { if (expectedResult.isEmpty() || regenerate) { expectedFile.writeText(actualResult) } else { - assertEquals(expectedResult, actualResult) + assertEquals(expectedResult, actualResult, "for grammar ${grammar.javaClass.simpleName} at ${testCasesFolder.name}") } } 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 1d27629f1..0f26f38cf 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 @@ -4,17 +4,19 @@ label="" 0 [label = "Nonterminal A, input: [0, 1]", shape = invtrapezium] 1 [label = "Nonterminal B, input: [0, 1]", shape = invtrapezium] 2 [label = "Nonterminal C, input: [0, 1]", shape = invtrapezium] -3 [label = "Range , input: [0, 1], rsm: [A_0, A_1]", shape = ellipse] -4 [label = "Range , input: [0, 1], rsm: [B_0, B_1]", shape = ellipse] -5 [label = "Range , input: [0, 1], rsm: [C_0, C_1]", shape = ellipse] -6 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] -7 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] -0->3 -1->4 -2->5 +3 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +4 [label = "Range , input: [0, 1], rsm: [A_0, A_1]", shape = ellipse] +5 [label = "Range , input: [0, 1], rsm: [B_0, B_1]", shape = ellipse] +6 [label = "Range , input: [0, 1], rsm: [C_0, C_1]", shape = ellipse] +7 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +8 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] +0->4 +1->5 +2->6 3->7 -4->2 -5->7 -6->1 -6->0 +4->8 +5->2 +6->8 +7->1 +7->0 } diff --git a/test-shared/src/test/resources/correctness/tree/AmbiguousAStar1/simple/input.dot b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar1/simple/input.dot new file mode 100644 index 000000000..2ff53cdf3 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar1/simple/input.dot @@ -0,0 +1,6 @@ +digraph Input { + start -> 0; + 0 -> 1 [label = "a"]; + 1 -> 2 [label = "a"]; + 2 -> 3 [label = "a"]; +} \ No newline at end of file diff --git a/test-shared/src/test/resources/correctness/tree/AmbiguousAStar1/simple/result.dot b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar1/simple/result.dot new file mode 100644 index 000000000..5432708a8 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar1/simple/result.dot @@ -0,0 +1,11 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +1 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +2 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +3 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] +0->2 +2->3 +2->0 +} diff --git a/test-shared/src/test/resources/correctness/tree/AmbiguousAStar2/simple/input.dot b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar2/simple/input.dot new file mode 100644 index 000000000..2ff53cdf3 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar2/simple/input.dot @@ -0,0 +1,6 @@ +digraph Input { + start -> 0; + 0 -> 1 [label = "a"]; + 1 -> 2 [label = "a"]; + 2 -> 3 [label = "a"]; +} \ No newline at end of file diff --git a/test-shared/src/test/resources/correctness/tree/AmbiguousAStar2/simple/result.dot b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar2/simple/result.dot new file mode 100644 index 000000000..50e0726a4 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar2/simple/result.dot @@ -0,0 +1,57 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Intermediate input: 1, rsm: S_2, input: [0, 2]", shape = plain] +1 [label = "Intermediate input: 1, rsm: S_2, input: [0, 3]", shape = plain] +2 [label = "Intermediate input: 2, rsm: S_2, input: [0, 3]", shape = plain] +3 [label = "Intermediate input: 2, rsm: S_2, input: [1, 3]", shape = plain] +4 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +5 [label = "Nonterminal S, input: [0, 2]", shape = invtrapezium] +6 [label = "Nonterminal S, input: [0, 3]", shape = invtrapezium] +7 [label = "Nonterminal S, input: [1, 2]", shape = invtrapezium] +8 [label = "Nonterminal S, input: [1, 2]", shape = invtrapezium] +9 [label = "Nonterminal S, input: [1, 3]", shape = invtrapezium] +10 [label = "Nonterminal S, input: [2, 3]", shape = invtrapezium] +11 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +12 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +13 [label = "Range , input: [0, 2], rsm: [S_0, S_1]", shape = ellipse] +14 [label = "Range , input: [0, 2], rsm: [S_0, S_2]", shape = ellipse] +15 [label = "Range , input: [0, 3], rsm: [S_0, S_1]", shape = ellipse] +16 [label = "Range , input: [1, 2], rsm: [S_0, S_1]", shape = ellipse] +17 [label = "Range , input: [1, 2], rsm: [S_0, S_2]", shape = ellipse] +18 [label = "Range , input: [1, 2], rsm: [S_2, S_1]", shape = ellipse] +19 [label = "Range , input: [1, 3], rsm: [S_0, S_1]", shape = ellipse] +20 [label = "Range , input: [1, 3], rsm: [S_2, S_1]", shape = ellipse] +21 [label = "Range , input: [2, 3], rsm: [S_0, S_1]", shape = ellipse] +22 [label = "Range , input: [2, 3], rsm: [S_2, S_1]", shape = ellipse] +23 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] +24 [label = "Terminal 'a', input: [1, 2]", shape = rectangle] +25 [label = "Terminal 'a', input: [2, 3]", shape = rectangle] +0->12 +0->18 +1->12 +1->20 +2->14 +2->22 +3->17 +3->22 +4->11 +5->13 +6->15 +7->16 +9->19 +10->21 +11->23 +12->4 +13->0 +14->5 +15->1 +15->2 +16->24 +17->7 +18->7 +19->3 +20->9 +21->25 +22->10 +} diff --git a/test-shared/src/test/resources/correctness/tree/AmbiguousAStar3/simple/input.dot b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar3/simple/input.dot new file mode 100644 index 000000000..2ff53cdf3 --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar3/simple/input.dot @@ -0,0 +1,6 @@ +digraph Input { + start -> 0; + 0 -> 1 [label = "a"]; + 1 -> 2 [label = "a"]; + 2 -> 3 [label = "a"]; +} \ No newline at end of file diff --git a/test-shared/src/test/resources/correctness/tree/AmbiguousAStar3/simple/result.dot b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar3/simple/result.dot new file mode 100644 index 000000000..368e3ef3e --- /dev/null +++ b/test-shared/src/test/resources/correctness/tree/AmbiguousAStar3/simple/result.dot @@ -0,0 +1,10 @@ +digraph g { +labelloc="t" +label="" +0 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +1 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +2 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] +0->1 +1->2 +1->0 +} diff --git a/test-shared/src/test/resources/correctness/tree/Epsilon/epsilon/result.dot b/test-shared/src/test/resources/correctness/tree/Epsilon/epsilon/result.dot index b7962fa25..964b3aa24 100644 --- a/test-shared/src/test/resources/correctness/tree/Epsilon/epsilon/result.dot +++ b/test-shared/src/test/resources/correctness/tree/Epsilon/epsilon/result.dot @@ -2,6 +2,8 @@ digraph g { labelloc="t" label="" 0 [label = "Epsilon RSM: S_0, input: [0, 0]", shape = invhouse] -1 [label = "Range , input: [0, 0], rsm: [S_0, S_0]", shape = ellipse] -1->0 +1 [label = "Nonterminal S, input: [0, 0]", shape = invtrapezium] +2 [label = "Range , input: [0, 0], rsm: [S_0, S_0]", shape = ellipse] +1->2 +2->0 } 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 index 2f93dc957..d3625402d 100644 --- a/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/result.dot +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/oneVertex/result.dot @@ -5,22 +5,22 @@ label="" 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 +4 [label = "Nonterminal S, input: [0, 0]", shape = invtrapezium] +5 [label = "Range , input: [0, 0], rsm: [S_0, S_0]", shape = ellipse] +6 [label = "Range , input: [0, 0], rsm: [S_0, S_1]", shape = ellipse] +7 [label = "Range , input: [0, 0], rsm: [S_0, S_2]", shape = ellipse] +8 [label = "Range , input: [0, 0], rsm: [S_1, S_2]", shape = ellipse] +9 [label = "Range , input: [0, 0], rsm: [S_2, S_0]", shape = ellipse] +10 [label = "Terminal '(', input: [0, 0]", shape = rectangle] +11 [label = "Terminal ')', input: [0, 0]", shape = rectangle] +1->6 +1->8 +2->7 +2->9 +5->0 +5->2 +6->10 +7->1 +8->3 +9->11 } 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 index 130fa1bc3..b06a092e2 100644 --- a/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/result.dot +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/secondWorstCase/result.dot @@ -1,122 +1,110 @@ 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 +0 [label = "Intermediate input: 0, rsm: S_0, input: [3, 3]", shape = plain] +1 [label = "Intermediate input: 0, rsm: S_1, input: [3, 0]", shape = plain] +2 [label = "Intermediate input: 0, rsm: S_1, input: [3, 1]", shape = plain] +3 [label = "Intermediate input: 0, rsm: S_1, input: [3, 2]", shape = plain] +4 [label = "Intermediate input: 0, rsm: S_2, input: [0, 1]", shape = plain] +5 [label = "Intermediate input: 0, rsm: S_2, input: [3, 1]", shape = plain] +6 [label = "Intermediate input: 1, rsm: S_2, input: [0, 2]", shape = plain] +7 [label = "Intermediate input: 1, rsm: S_2, input: [3, 2]", shape = plain] +8 [label = "Intermediate input: 2, rsm: S_2, input: [3, 0]", shape = plain] +9 [label = "Intermediate input: 3, rsm: S_1, input: [0, 0]", shape = plain] +10 [label = "Intermediate input: 3, rsm: S_1, input: [0, 1]", shape = plain] +11 [label = "Intermediate input: 3, rsm: S_1, input: [3, 0]", shape = plain] +12 [label = "Intermediate input: 3, rsm: S_1, input: [3, 1]", shape = plain] +13 [label = "Intermediate input: 3, rsm: S_1, input: [3, 2]", shape = plain] +14 [label = "Nonterminal S, input: [0, 0]", shape = invtrapezium] +15 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +16 [label = "Nonterminal S, input: [0, 1]", shape = invtrapezium] +17 [label = "Nonterminal S, input: [0, 2]", shape = invtrapezium] +18 [label = "Nonterminal S, input: [3, 0]", shape = invtrapezium] +19 [label = "Nonterminal S, input: [3, 1]", shape = invtrapezium] +20 [label = "Nonterminal S, input: [3, 2]", shape = invtrapezium] +21 [label = "Range , input: [0, 0], rsm: [S_0, S_2]", shape = ellipse] +22 [label = "Range , input: [0, 0], rsm: [S_1, S_2]", shape = ellipse] +23 [label = "Range , input: [0, 1], rsm: [S_0, S_0]", shape = ellipse] +24 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +25 [label = "Range , input: [0, 1], rsm: [S_1, S_2]", shape = ellipse] +26 [label = "Range , input: [0, 1], rsm: [S_2, S_0]", shape = ellipse] +27 [label = "Range , input: [0, 2], rsm: [S_0, S_0]", shape = ellipse] +28 [label = "Range , input: [0, 2], rsm: [S_1, S_2]", shape = ellipse] +29 [label = "Range , input: [0, 3], rsm: [S_0, S_1]", shape = ellipse] +30 [label = "Range , input: [1, 2], rsm: [S_2, S_0]", shape = ellipse] +31 [label = "Range , input: [2, 0], rsm: [S_2, S_0]", shape = ellipse] +32 [label = "Range , input: [3, 0], rsm: [S_0, S_0]", shape = ellipse] +33 [label = "Range , input: [3, 0], rsm: [S_0, S_1]", shape = ellipse] +34 [label = "Range , input: [3, 0], rsm: [S_0, S_2]", shape = ellipse] +35 [label = "Range , input: [3, 0], rsm: [S_1, S_2]", shape = ellipse] +36 [label = "Range , input: [3, 1], rsm: [S_0, S_0]", shape = ellipse] +37 [label = "Range , input: [3, 1], rsm: [S_0, S_2]", shape = ellipse] +38 [label = "Range , input: [3, 1], rsm: [S_1, S_2]", shape = ellipse] +39 [label = "Range , input: [3, 2], rsm: [S_0, S_0]", shape = ellipse] +40 [label = "Range , input: [3, 2], rsm: [S_0, S_2]", shape = ellipse] +41 [label = "Range , input: [3, 2], rsm: [S_1, S_2]", shape = ellipse] +42 [label = "Range , input: [3, 3], rsm: [S_0, S_1]", shape = ellipse] +43 [label = "Terminal '(', input: [0, 3]", shape = rectangle] +44 [label = "Terminal '(', input: [3, 0]", shape = rectangle] +45 [label = "Terminal ')', input: [0, 1]", shape = rectangle] +46 [label = "Terminal ')', input: [1, 2]", shape = rectangle] +47 [label = "Terminal ')', input: [2, 0]", shape = rectangle] +0->32 +0->29 1->33 -2->37 +1->22 +2->33 2->25 -3->37 +3->33 3->28 -4->37 -4->32 -5->24 -5->29 -6->38 -6->29 -7->27 -7->34 -8->41 -8->34 -9->31 +4->21 +4->26 +5->34 +5->26 +6->24 +6->30 +7->37 +7->30 +8->40 +8->31 +9->29 9->35 -10->44 -10->35 -11->33 -11->39 -12->33 +10->29 +10->38 +11->42 +11->35 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 +12->38 +13->42 +13->41 +15->23 +17->27 +18->32 +19->36 +20->39 +21->9 +22->14 +23->4 +24->10 +25->15 +26->45 +27->6 +28->17 +29->43 +30->46 +31->47 +32->8 +33->44 +34->1 +34->11 +35->18 +36->5 +37->12 +37->2 +38->19 +39->7 +40->3 +40->13 +41->20 +42->0 } 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 index ec8facdb3..d8f115ce6 100644 --- a/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/result.dot +++ b/test-shared/src/test/resources/correctness/tree/LoopDyck/twoPairs/result.dot @@ -8,48 +8,50 @@ label="" 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 [label = "Nonterminal S, input: [0, 4]", shape = invtrapezium] +8 [label = "Nonterminal S, input: [1, 1]", shape = invtrapezium] +9 [label = "Nonterminal S, input: [3, 3]", shape = invtrapezium] +10 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +11 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +12 [label = "Range , input: [0, 2], rsm: [S_0, S_0]", shape = ellipse] +13 [label = "Range , input: [0, 3], rsm: [S_0, S_1]", shape = ellipse] +14 [label = "Range , input: [0, 3], rsm: [S_0, S_2]", shape = ellipse] +15 [label = "Range , input: [0, 4], rsm: [S_0, S_0]", shape = ellipse] +16 [label = "Range , input: [1, 1], rsm: [S_0, S_0]", shape = ellipse] +17 [label = "Range , input: [1, 1], rsm: [S_1, S_2]", shape = ellipse] +18 [label = "Range , input: [1, 2], rsm: [S_2, S_0]", shape = ellipse] +19 [label = "Range , input: [2, 3], rsm: [S_0, S_1]", shape = ellipse] +20 [label = "Range , input: [3, 3], rsm: [S_0, S_0]", shape = ellipse] +21 [label = "Range , input: [3, 3], rsm: [S_1, S_2]", shape = ellipse] +22 [label = "Range , input: [3, 4], rsm: [S_2, S_0]", shape = ellipse] +23 [label = "Terminal '(', input: [0, 1]", shape = rectangle] +24 [label = "Terminal '(', input: [2, 3]", shape = rectangle] +25 [label = "Terminal ')', input: [1, 2]", shape = rectangle] +26 [label = "Terminal ')', input: [3, 4]", shape = rectangle] +2->10 +2->17 +3->11 +3->18 +4->12 +4->19 +5->13 +5->21 +6->14 +6->22 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 +8->16 +9->20 +10->23 +11->2 +12->3 +13->4 +14->5 +15->6 +16->0 +17->8 +18->25 +19->24 +20->1 +21->9 +22->26 } 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 53b75dfe8..489d94ae7 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 @@ -5,31 +5,33 @@ label="" 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] -6 [label = "Range , input: [0, 2], rsm: [A_0, A_2]", shape = ellipse] -7 [label = "Range , input: [0, 2], rsm: [S_0, S_1]", shape = ellipse] -8 [label = "Range , input: [0, 3], rsm: [S_0, S_3]", shape = ellipse] -9 [label = "Range , input: [1, 2], rsm: [A_1, A_2]", shape = ellipse] -10 [label = "Range , input: [1, 2], rsm: [S_2, S_1]", shape = ellipse] -11 [label = "Range , input: [2, 3], rsm: [S_1, S_3]", shape = ellipse] -12 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] -13 [label = "Terminal 'b', input: [1, 2]", shape = rectangle] -14 [label = "Terminal 'c', input: [2, 3]", shape = rectangle] -0->4 -0->9 -1->5 -1->10 -2->7 -2->11 -3->6 -4->12 -5->12 -6->0 -7->3 -7->1 -8->2 -9->13 -10->13 +4 [label = "Nonterminal S, input: [0, 3]", shape = invtrapezium] +5 [label = "Range , input: [0, 1], rsm: [A_0, A_1]", shape = ellipse] +6 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +7 [label = "Range , input: [0, 2], rsm: [A_0, A_2]", shape = ellipse] +8 [label = "Range , input: [0, 2], rsm: [S_0, S_1]", shape = ellipse] +9 [label = "Range , input: [0, 3], rsm: [S_0, S_3]", shape = ellipse] +10 [label = "Range , input: [1, 2], rsm: [A_1, A_2]", shape = ellipse] +11 [label = "Range , input: [1, 2], rsm: [S_2, S_1]", shape = ellipse] +12 [label = "Range , input: [2, 3], rsm: [S_1, S_3]", shape = ellipse] +13 [label = "Terminal 'a', input: [0, 1]", shape = rectangle] +14 [label = "Terminal 'b', input: [1, 2]", shape = rectangle] +15 [label = "Terminal 'c', input: [2, 3]", shape = rectangle] +0->5 +0->10 +1->6 +1->11 +2->8 +2->12 +3->7 +4->9 +5->13 +6->13 +7->0 +8->3 +8->1 +9->2 +10->14 11->14 +12->15 } 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 851619986..1f23a36c4 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 @@ -4,24 +4,26 @@ label="" 0 [label = "Epsilon RSM: S_0, input: [1, 1]", shape = invhouse] 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] -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 [label = "Nonterminal S, input: [0, 2]", shape = invtrapezium] +4 [label = "Nonterminal S, input: [1, 1]", shape = invtrapezium] +5 [label = "Range , input: [0, 1], rsm: [S_0, S_1]", shape = ellipse] +6 [label = "Range , input: [0, 1], rsm: [S_0, S_2]", shape = ellipse] +7 [label = "Range , input: [0, 2], rsm: [S_0, S_3]", shape = ellipse] +8 [label = "Range , input: [1, 1], rsm: [S_0, S_0]", shape = ellipse] +9 [label = "Range , input: [1, 1], rsm: [S_1, S_2]", shape = ellipse] +10 [label = "Range , input: [1, 2], rsm: [S_2, S_3]", shape = ellipse] +11 [label = "Terminal '(', input: [0, 1]", shape = rectangle] +12 [label = "Terminal ')', input: [1, 2]", shape = rectangle] +1->5 +1->9 +2->6 +2->10 3->7 -4->10 -5->1 -6->2 -7->0 -8->3 -9->11 +4->8 +5->11 +6->1 +7->2 +8->0 +9->4 +10->12 } diff --git a/test-shared/src/test/resources/todo/LoopDyck/minimalWorstCase/input.dot b/test-shared/src/test/resources/todo/LoopDyck/minimalWorstCase/input.dot new file mode 100644 index 000000000..7c08420c5 --- /dev/null +++ b/test-shared/src/test/resources/todo/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/todo/LoopDyck/minimalWorstCase/result.dot b/test-shared/src/test/resources/todo/LoopDyck/minimalWorstCase/result.dot new file mode 100644 index 000000000..8e702aee9 --- /dev/null +++ b/test-shared/src/test/resources/todo/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 +}