Skip to content

Commit

Permalink
refactor: Convert ANTLR DateExpression parser to a recursive decent p…
Browse files Browse the repository at this point in the history
…arser #1615
  • Loading branch information
rholshausen committed Oct 27, 2022
1 parent 739a40d commit 5d78360
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import au.com.dius.pact.core.support.generators.expressions.DateExpressionParser
import au.com.dius.pact.core.support.generators.expressions.DateOffsetType
import au.com.dius.pact.core.support.generators.expressions.Operation
import mu.KLogging
import org.antlr.v4.runtime.CharStreams
import org.antlr.v4.runtime.CommonTokenStream
import java.time.DayOfWeek
import java.time.Month
import java.time.OffsetDateTime
Expand Down Expand Up @@ -142,17 +140,11 @@ object DateExpression : KLogging() {
}

private fun parseDateExpression(expression: String): Result<ParsedDateExpression, String> {
val charStream = CharStreams.fromString(expression)
val lexer = DateExpressionLexer(charStream)
val tokens = CommonTokenStream(lexer)
val parser = DateExpressionParser(tokens)
val errorListener = ErrorListener()
parser.addErrorListener(errorListener)
val result = parser.expression()
return if (errorListener.errors.isNotEmpty()) {
Err("Error parsing expression: ${errorListener.errors.joinToString(", ")}")
} else {
Ok(ParsedDateExpression(result.dateBase, result.adj))
val lexer = DateExpressionLexer(expression)
val parser = DateExpressionParser(lexer)
return when (val result = parser.expression()) {
is Err -> Err("Error parsing expression: ${result.error}")
is Ok -> Ok(ParsedDateExpression(result.value.first, result.value.second.toMutableList()))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package au.com.dius.pact.model.generators
package au.com.dius.pact.core.model.generators

import au.com.dius.pact.core.model.generators.DateExpression
import spock.lang.Specification
import spock.lang.Unroll

Expand Down Expand Up @@ -55,8 +54,8 @@ class DateExpressionSpec extends Specification {
where:

expression | expected
'+' | 'Error parsing expression: line 1:1 mismatched input \'<EOF>\' expecting INT'
'now +' | 'Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
'+' | 'Error parsing expression: Was expecting an integer at index 1'
'now +' | 'Error parsing expression: Was expecting an integer at index 5'
'tomorr' | /^Error parsing expression.*/
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package au.com.dius.pact.model.generators
package au.com.dius.pact.core.model.generators

import au.com.dius.pact.core.model.generators.DateTimeExpression
import spock.lang.Specification
import spock.lang.Unroll

Expand Down Expand Up @@ -102,12 +101,12 @@ class DateTimeExpressionSpec extends Specification {
where:

expression | expected
'+' | 'Error parsing expression: line 1:1 mismatched input \'<EOF>\' expecting INT'
'now +' | 'Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
'+' | 'Error parsing expression: Was expecting an integer at index 1'
'now +' | 'Error parsing expression: Was expecting an integer at index 5'
'tomorr' | /^Error parsing expression.*/
'now @ +' | 'Error parsing expression: line 1:7 mismatched input \'<EOF>\' expecting INT'
'+ @ +' | 'Error parsing expression: line 1:2 mismatched input \'<EOF>\' expecting INT, Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
'now+ @ now +' | 'Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT, Error parsing expression: line 1:12 mismatched input \'<EOF>\' expecting INT'
'+ @ +' | 'Error parsing expression: Was expecting an integer at index 2, Error parsing expression: line 1:5 mismatched input \'<EOF>\' expecting INT'
'now+ @ now +' | 'Error parsing expression: Was expecting an integer at index 5, Error parsing expression: line 1:12 mismatched input \'<EOF>\' expecting INT'
'now @ now +' | 'Error parsing expression: line 1:11 mismatched input \'<EOF>\' expecting INT'
'now @ noo' | /^Error parsing expression.*/
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ data class Version(
}

companion object {
val INT = Regex("^\\d+")

@JvmStatic
fun parse(version: String): Result<Version, String> {
val lexer = StringLexer(version)

val major = when (val result = parseInt(lexer)) {
val major = when (val result = lexer.parseInt()) {
is Ok -> result.value
is Err -> return result
}
Expand All @@ -35,15 +33,15 @@ data class Version(
return Err(err)
}

val minor = when (val result = parseInt(lexer)) {
val minor = when (val result = lexer.parseInt()) {
is Ok -> result.value
is Err -> return result
}

return when {
lexer.peekNextChar() == '.' -> {
lexer.advance()
when (val result = parseInt(lexer)) {
when (val result = lexer.parseInt()) {
is Ok -> if (lexer.empty) {
Ok(Version(major, minor, result.value))
} else {
Expand All @@ -64,12 +62,5 @@ data class Version(
else -> "Was expecting a '$c' at index ${lexer.index - 1} but got '$ch'"
}
}

private fun parseInt(lexer: StringLexer): Result<Int, String> {
return when (val result = lexer.matchRegex(INT)) {
null -> Err("Was expecting an integer at index ${lexer.index}")
else -> Ok(result.toInt())
}
}
}
}
Loading

0 comments on commit 5d78360

Please sign in to comment.