@@ -49,7 +49,7 @@ internal fun <T> List<ParserStructure<T>>.concat(): ParserStructure<T> {
4949 ParserStructure (operations, followedBy.map { it.append(other) })
5050 }
5151
52- fun ParserStructure<T>.simplify ( ): ParserStructure <T > {
52+ fun ParserStructure<T>.simplifyAndAppend ( other : ParserStructure < T > ): ParserStructure <T > {
5353 val newOperations = mutableListOf<ParserOperation <T >>()
5454 var currentNumberSpan: MutableList <NumberConsumer <T >>? = null
5555 val unconditionalModifications = mutableListOf<UnconditionalModification <T >>()
@@ -72,8 +72,37 @@ internal fun <T> List<ParserStructure<T>>.concat(): ParserStructure<T> {
7272 newOperations.add(op)
7373 }
7474 }
75+
76+ if (followedBy.isEmpty()) {
77+ if (other.operations.isNotEmpty()) {
78+ if (currentNumberSpan == null ) {
79+ val firstOperation = other.operations.first()
80+ if (firstOperation is NumberSpanParserOperation ) {
81+ newOperations.add(other.operations.first())
82+ newOperations.addAll(unconditionalModifications)
83+ newOperations.addAll(other.operations.drop(1 ))
84+ } else {
85+ newOperations.addAll(unconditionalModifications)
86+ newOperations.addAll(other.operations)
87+ }
88+ } else {
89+ val firstOperation = other.operations.first()
90+ if (firstOperation is NumberSpanParserOperation ) {
91+ newOperations.add(NumberSpanParserOperation (currentNumberSpan + firstOperation.consumers))
92+ newOperations.addAll(unconditionalModifications)
93+ newOperations.addAll(other.operations.drop(1 ))
94+ } else {
95+ newOperations.add(NumberSpanParserOperation (currentNumberSpan))
96+ newOperations.addAll(unconditionalModifications)
97+ newOperations.addAll(other.operations)
98+ }
99+ }
100+ return ParserStructure (newOperations, other.followedBy)
101+ }
102+ }
103+
75104 val mergedTails = followedBy.flatMap {
76- val simplified = it.simplify( )
105+ val simplified = it.simplifyAndAppend(other )
77106 // parser `ParserStructure(emptyList(), p)` is equivalent to `p`,
78107 // unless `p` is empty. For example, ((a|b)|(c|d)) is equivalent to (a|b|c|d).
79108 // As a special case, `ParserStructure(emptyList(), emptyList())` represents a parser that recognizes an empty
@@ -82,7 +111,7 @@ internal fun <T> List<ParserStructure<T>>.concat(): ParserStructure<T> {
82111 simplified.followedBy.ifEmpty { listOf (simplified) }
83112 else
84113 listOf (simplified)
85- }
114+ }.ifEmpty { other.followedBy }
86115 return if (currentNumberSpan == null ) {
87116 // the last operation was not a number span, or it was a number span that we are allowed to interrupt
88117 newOperations.addAll(unconditionalModifications)
@@ -127,8 +156,7 @@ internal fun <T> List<ParserStructure<T>>.concat(): ParserStructure<T> {
127156 ParserStructure (newOperations, newTails)
128157 }
129158 }
130- val naiveParser = foldRight(ParserStructure <T >(emptyList(), emptyList())) { parser, acc -> parser.append(acc) }
131- return naiveParser.simplify()
159+ return foldRight(ParserStructure (emptyList(), emptyList())) { parser, acc -> parser.simplifyAndAppend(acc) }
132160}
133161
134162internal interface Copyable <Self > {
0 commit comments