Skip to content

Commit 5d78360

Browse files
committed
refactor: Convert ANTLR DateExpression parser to a recursive decent parser #1615
1 parent 739a40d commit 5d78360

File tree

7 files changed

+327
-136
lines changed

7 files changed

+327
-136
lines changed

core/model/src/main/kotlin/au/com/dius/pact/core/model/generators/DateExpression.kt

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import au.com.dius.pact.core.support.generators.expressions.DateExpressionParser
1010
import au.com.dius.pact.core.support.generators.expressions.DateOffsetType
1111
import au.com.dius.pact.core.support.generators.expressions.Operation
1212
import mu.KLogging
13-
import org.antlr.v4.runtime.CharStreams
14-
import org.antlr.v4.runtime.CommonTokenStream
1513
import java.time.DayOfWeek
1614
import java.time.Month
1715
import java.time.OffsetDateTime
@@ -142,17 +140,11 @@ object DateExpression : KLogging() {
142140
}
143141

144142
private fun parseDateExpression(expression: String): Result<ParsedDateExpression, String> {
145-
val charStream = CharStreams.fromString(expression)
146-
val lexer = DateExpressionLexer(charStream)
147-
val tokens = CommonTokenStream(lexer)
148-
val parser = DateExpressionParser(tokens)
149-
val errorListener = ErrorListener()
150-
parser.addErrorListener(errorListener)
151-
val result = parser.expression()
152-
return if (errorListener.errors.isNotEmpty()) {
153-
Err("Error parsing expression: ${errorListener.errors.joinToString(", ")}")
154-
} else {
155-
Ok(ParsedDateExpression(result.dateBase, result.adj))
143+
val lexer = DateExpressionLexer(expression)
144+
val parser = DateExpressionParser(lexer)
145+
return when (val result = parser.expression()) {
146+
is Err -> Err("Error parsing expression: ${result.error}")
147+
is Ok -> Ok(ParsedDateExpression(result.value.first, result.value.second.toMutableList()))
156148
}
157149
}
158150
}

core/model/src/test/groovy/au/com/dius/pact/core/model/generators/DateExpressionSpec.groovy

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
package au.com.dius.pact.model.generators
1+
package au.com.dius.pact.core.model.generators
22

3-
import au.com.dius.pact.core.model.generators.DateExpression
43
import spock.lang.Specification
54
import spock.lang.Unroll
65

@@ -55,8 +54,8 @@ class DateExpressionSpec extends Specification {
5554
where:
5655

5756
expression | expected
58-
'+' | 'Error parsing expression: line 1:1 mismatched input \'<EOF>\' expecting INT'
59-
'now +' | 'Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
57+
'+' | 'Error parsing expression: Was expecting an integer at index 1'
58+
'now +' | 'Error parsing expression: Was expecting an integer at index 5'
6059
'tomorr' | /^Error parsing expression.*/
6160
}
6261
}

core/model/src/test/groovy/au/com/dius/pact/core/model/generators/DateTimeExpressionSpec.groovy

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
package au.com.dius.pact.model.generators
1+
package au.com.dius.pact.core.model.generators
22

3-
import au.com.dius.pact.core.model.generators.DateTimeExpression
43
import spock.lang.Specification
54
import spock.lang.Unroll
65

@@ -102,12 +101,12 @@ class DateTimeExpressionSpec extends Specification {
102101
where:
103102

104103
expression | expected
105-
'+' | 'Error parsing expression: line 1:1 mismatched input \'<EOF>\' expecting INT'
106-
'now +' | 'Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
104+
'+' | 'Error parsing expression: Was expecting an integer at index 1'
105+
'now +' | 'Error parsing expression: Was expecting an integer at index 5'
107106
'tomorr' | /^Error parsing expression.*/
108107
'now @ +' | 'Error parsing expression: line 1:7 mismatched input \'<EOF>\' expecting INT'
109-
'+ @ +' | 'Error parsing expression: line 1:2 mismatched input \'<EOF>\' expecting INT, Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
110-
'now+ @ now +' | 'Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT, Error parsing expression: line 1:12 mismatched input \'<EOF>\' expecting INT'
108+
'+ @ +' | 'Error parsing expression: Was expecting an integer at index 2, Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
109+
'now+ @ now +' | 'Error parsing expression: Was expecting an integer at index 5, Error parsing expression: line 1:12 mismatched input \'<EOF>\' expecting INT'
111110
'now @ now +' | 'Error parsing expression: line 1:11 mismatched input \'<EOF>\' expecting INT'
112111
'now @ noo' | /^Error parsing expression.*/
113112
}

core/support/src/main/antlr/au/com/dius/pact/core/support/generators/expressions/DateExpression.g4

Lines changed: 0 additions & 99 deletions
This file was deleted.

core/support/src/main/kotlin/au/com/dius/pact/core/support/Version.kt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@ data class Version(
1919
}
2020

2121
companion object {
22-
val INT = Regex("^\\d+")
23-
2422
@JvmStatic
2523
fun parse(version: String): Result<Version, String> {
2624
val lexer = StringLexer(version)
2725

28-
val major = when (val result = parseInt(lexer)) {
26+
val major = when (val result = lexer.parseInt()) {
2927
is Ok -> result.value
3028
is Err -> return result
3129
}
@@ -35,15 +33,15 @@ data class Version(
3533
return Err(err)
3634
}
3735

38-
val minor = when (val result = parseInt(lexer)) {
36+
val minor = when (val result = lexer.parseInt()) {
3937
is Ok -> result.value
4038
is Err -> return result
4139
}
4240

4341
return when {
4442
lexer.peekNextChar() == '.' -> {
4543
lexer.advance()
46-
when (val result = parseInt(lexer)) {
44+
when (val result = lexer.parseInt()) {
4745
is Ok -> if (lexer.empty) {
4846
Ok(Version(major, minor, result.value))
4947
} else {
@@ -64,12 +62,5 @@ data class Version(
6462
else -> "Was expecting a '$c' at index ${lexer.index - 1} but got '$ch'"
6563
}
6664
}
67-
68-
private fun parseInt(lexer: StringLexer): Result<Int, String> {
69-
return when (val result = lexer.matchRegex(INT)) {
70-
null -> Err("Was expecting an integer at index ${lexer.index}")
71-
else -> Ok(result.toInt())
72-
}
73-
}
7465
}
7566
}

0 commit comments

Comments
 (0)