Skip to content

Commit

Permalink
feat(grammar): Support timestamp literals
Browse files Browse the repository at this point in the history
  • Loading branch information
felipebz committed May 25, 2024
1 parent 7742599 commit bc26d2b
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DateChannel(private val regexpChannel: RegexpChannel)

override fun consume(code: CodeReader, output: LexerOutput): Boolean {
val nextChar = code.peek().toChar().lowercaseChar()
if (nextChar != 'd') {
if (nextChar != 'd' && nextChar != 't') {
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ object PlSqlLexer {

private const val DATE_LITERAL = """(?i)(?:DATE\s*?'\d{4}-\d{2}-\d{2}')"""

private const val TIMESTAMP_LITERAL = """(?i)TIMESTAMP\s*?'\d{4}-\d{2}-\d{2}\s++\d{1,2}:\d{2}:\d{2}(?:.\d{1,9})?(?:\s++[A-Z0-9_/+-:]++(?:\s++[A-Z0-9_/+-]{1,5})?)?'"""

private val SIMPLE_IDENTIFIER = and("""[\w\p{L}]""", o2n("""[\w\p{L}#$]"""))

private const val QUOTED_IDENTIFIER = """".+?""""
Expand All @@ -69,6 +71,7 @@ object PlSqlLexer {
.withChannel(IntegerChannel())
.withChannel(StringChannel(regexp(PlSqlTokenType.STRING_LITERAL, STRING_LITERAL)))
.withChannel(DateChannel(regexp(PlSqlTokenType.DATE_LITERAL, DATE_LITERAL)))
.withChannel(DateChannel(regexp(PlSqlTokenType.TIMESTAMP_LITERAL, TIMESTAMP_LITERAL)))
.withChannel(IdentifierChannel(IdentifierAndKeywordChannel(or(SIMPLE_IDENTIFIER, QUOTED_IDENTIFIER), false,
PlSqlKeyword.entries.toTypedArray()
)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ enum class PlSqlGrammar : GrammarRuleKey {
b.rule(INQUIRY_DIRECTIVE).define(DOUBLEDOLLAR, IDENTIFIER_NAME)

b.rule(LITERAL).define(b.firstOf(NULL_LITERAL, BOOLEAN_LITERAL, NUMERIC_LITERAL,
FLOATING_POINT_LITERAL, CHARACTER_LITERAL, DATE_LITERAL, INTERVAL_LITERAL, INQUIRY_DIRECTIVE))
FLOATING_POINT_LITERAL, CHARACTER_LITERAL, DATE_LITERAL, TIMESTAMP_LITERAL, INTERVAL_LITERAL, INQUIRY_DIRECTIVE))
}

private fun createOperators(b: PlSqlGrammarBuilder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ enum class PlSqlTokenType : TokenType {
STRING_LITERAL,
INTEGER_LITERAL,
NUMBER_LITERAL,
DATE_LITERAL;
DATE_LITERAL,
TIMESTAMP_LITERAL;

override val value = name

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ class PlSqlLexerTest {
assertThatIsToken("date '2015-01-01'", PlSqlTokenType.DATE_LITERAL)
}

@Test
fun timestampLiteral() {
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("timestamp '2015-01-01 01:01:01'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("timestamp'2015-01-01 01:01:01'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("timestamp '2015-01-01 01:01:01'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01.0'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01.123456789'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01 -3:00'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01 -03:00'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01 America/Sao_Paulo'", PlSqlTokenType.TIMESTAMP_LITERAL)
assertThatIsToken("TIMESTAMP '2015-01-01 01:01:01 America/Sao_Paulo -03'", PlSqlTokenType.TIMESTAMP_LITERAL)
}

private fun assertThatIsToken(sourceCode: String, tokenType: TokenType) {
assertThat(lexer.lex(sourceCode)).hasToken(sourceCode, tokenType)
}
Expand Down

0 comments on commit bc26d2b

Please sign in to comment.