Skip to content

Commit

Permalink
Add support for hexadecimal, octal and binary integer literals
Browse files Browse the repository at this point in the history
As defined by SQL 2023
  • Loading branch information
martint committed Jun 8, 2023
1 parent 6f02ea9 commit 7cba489
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
15 changes: 15 additions & 0 deletions core/trino-parser/src/main/antlr4/io/trino/sql/parser/SqlBase.g4
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,9 @@ BINARY_LITERAL

INTEGER_VALUE
: DECIMAL_INTEGER
| HEXADECIMAL_INTEGER
| OCTAL_INTEGER
| BINARY_INTEGER
;

DECIMAL_VALUE
Expand Down Expand Up @@ -1256,6 +1259,18 @@ fragment DECIMAL_INTEGER
: DIGIT ('_'? DIGIT)*
;

fragment HEXADECIMAL_INTEGER
: '0X' ('_'? (DIGIT | [A-F]))+
;

fragment OCTAL_INTEGER
: '0O' ('_'? [0-7])+
;

fragment BINARY_INTEGER
: '0B' ('_'? [01])+
;

fragment EXPONENT
: 'E' [+-]? DIGIT+
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private LongLiteral(Optional<NodeLocation> location, String value)
requireNonNull(value, "value is null");
try {
this.value = value;
this.parsedValue = Long.parseLong(value.replace("_", ""));
this.parsedValue = parse(value);
}
catch (NumberFormatException e) {
throw new ParsingException("Invalid numeric literal: " + value);
Expand Down Expand Up @@ -98,4 +98,22 @@ public boolean shallowEquals(Node other)

return parsedValue == ((LongLiteral) other).parsedValue;
}

private static long parse(String value)
{
value = value.replace("_", "");

if (value.startsWith("0x") || value.startsWith("0X")) {
return Long.parseLong(value.substring(2), 16);
}
else if (value.startsWith("0b") || value.startsWith("0B")) {
return Long.parseLong(value.substring(2), 2);
}
else if (value.startsWith("0o") || value.startsWith("0O")) {
return Long.parseLong(value.substring(2), 8);
}
else {
return Long.parseLong(value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -478,13 +478,55 @@ public void testNumbers()

assertThatThrownBy(() -> SQL_PARSER.createExpression("123_456._789_0123", new ParsingOptions()))
.isInstanceOf(ParsingException.class);

assertThat(expression("0x123_abc_def"))
.isEqualTo(new LongLiteral(new NodeLocation(1, 1), "0x123_abc_def"))
.satisfies(value -> assertThat(((LongLiteral) value).getParsedValue()).isEqualTo(4893429231L));

assertThat(expression("0X123_ABC_DEF"))
.isEqualTo(new LongLiteral(new NodeLocation(1, 1), "0X123_ABC_DEF"))
.satisfies(value -> assertThat(((LongLiteral) value).getParsedValue()).isEqualTo(4893429231L));

assertThatThrownBy(() -> SQL_PARSER.createExpression("0x123_ABC_DEF_", new ParsingOptions()))
.isInstanceOf(ParsingException.class);

assertThat(expression("0O012_345"))
.isEqualTo(new LongLiteral(new NodeLocation(1, 1), "0O012_345"))
.satisfies(value -> assertThat(((LongLiteral) value).getParsedValue()).isEqualTo(5349L));

assertThat(expression("0o012_345"))
.isEqualTo(new LongLiteral(new NodeLocation(1, 1), "0o012_345"))
.satisfies(value -> assertThat(((LongLiteral) value).getParsedValue()).isEqualTo(5349L));

assertThatThrownBy(() -> SQL_PARSER.createExpression("0o012_345_", new ParsingOptions()))
.isInstanceOf(ParsingException.class);

assertThat(expression("0B110_010"))
.isEqualTo(new LongLiteral(new NodeLocation(1, 1), "0B110_010"))
.satisfies(value -> assertThat(((LongLiteral) value).getParsedValue()).isEqualTo(50L));

assertThat(expression("0b110_010"))
.isEqualTo(new LongLiteral(new NodeLocation(1, 1), "0b110_010"))
.satisfies(value -> assertThat(((LongLiteral) value).getParsedValue()).isEqualTo(50L));

assertThatThrownBy(() -> SQL_PARSER.createExpression("0b110_010_", new ParsingOptions()))
.isInstanceOf(ParsingException.class);
}

@Test
public void testIdentifier()
{
assertThat(expression("_123_456"))
.isEqualTo(new Identifier(new NodeLocation(1, 1), "_123_456", false));

assertThat(expression("_0x123_ABC_DEF"))
.isEqualTo(new Identifier(new NodeLocation(1, 1), "_0x123_ABC_DEF", false));

assertThat(expression("_0o012_345"))
.isEqualTo(new Identifier(new NodeLocation(1, 1), "_0o012_345", false));

assertThat(expression("_0b110_010"))
.isEqualTo(new Identifier(new NodeLocation(1, 1), "_0b110_010", false));
}

@Test
Expand Down

0 comments on commit 7cba489

Please sign in to comment.