diff --git a/common/src/main/java/dev/cel/common/internal/Constants.java b/common/src/main/java/dev/cel/common/internal/Constants.java index 49bca7489..6d547a4e1 100644 --- a/common/src/main/java/dev/cel/common/internal/Constants.java +++ b/common/src/main/java/dev/cel/common/internal/Constants.java @@ -51,13 +51,13 @@ public final class Constants { public static CelConstant parseInt(String text) throws ParseException { int base; - if (text.startsWith("-0x")) { + if (text.startsWith("-0x") || text.startsWith("-0X")) { base = 16; // Strip off the sign and prefix. text = text.substring(3); // Add the sign back. text = "-" + text; - } else if (text.startsWith("0x")) { + } else if (text.startsWith("0x") || text.startsWith("0X")) { base = 16; text = text.substring(2); if (text.startsWith("-")) { @@ -83,7 +83,7 @@ public static CelConstant parseUint(String text) throws ParseException { throw new ParseException("Unsigned integer literal is missing trailing 'u' suffix", 0); } text = text.substring(0, text.length() - 1); - if (text.startsWith("0x")) { + if (text.startsWith("0x") || text.startsWith("0X")) { base = 16; text = text.substring(2); } else { diff --git a/parser/src/main/java/dev/cel/parser/Lexer.java b/parser/src/main/java/dev/cel/parser/Lexer.java index 602a6ef00..1d8fdfdaa 100644 --- a/parser/src/main/java/dev/cel/parser/Lexer.java +++ b/parser/src/main/java/dev/cel/parser/Lexer.java @@ -428,7 +428,6 @@ private void consumeWhitespaceAndComments() { case '\n': case ' ': case '\r': - case 11: // \v case '\t': position++; break; @@ -589,18 +588,12 @@ private Token consumeNumericLiteral() { } } else { advance(1); - if (c == '0' && consume('x')) { + if (c == '0' && (consume('x') || consume('X'))) { if (!consumeHexDigits()) { return setError( start, position, "integral literal missing digits after hexadecimal separator"); } TokenType tokenType = consumeIntegralSuffix(); - if (consumeIf(Lexer::isIdentTrailing)) { - return setError( - start, - position, - tokenType.getSymbol() + " literal has unexpected trailing characters"); - } return makeToken(tokenType, start, position); } consumeDigits(); @@ -622,10 +615,6 @@ && isDigit(content.get(position + 1))) { } } TokenType tokenType = floatingPoint ? TokenType.FLOAT : consumeIntegralSuffix(); - if (consumeIf(Lexer::isIdentTrailing)) { - return setError( - start, position, tokenType.getSymbol() + " literal has unexpected trailing characters"); - } return makeToken(tokenType, start, position); } diff --git a/parser/src/main/java/dev/cel/parser/PrattParser.java b/parser/src/main/java/dev/cel/parser/PrattParser.java index 829ac1dcc..4881afae0 100644 --- a/parser/src/main/java/dev/cel/parser/PrattParser.java +++ b/parser/src/main/java/dev/cel/parser/PrattParser.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelIssue; import dev.cel.common.CelOptions; @@ -524,21 +523,36 @@ private static CelExpr buildUnaryCall(long id, String function, CelExpr operand) private CelExpr parseSelectorChain() { Lexer.TokenType tok = peekToken.type; - CelExpr lhs = - (tok == Lexer.TokenType.EXCLAMATION || tok == Lexer.TokenType.MINUS) - ? parseUnaryOps() - : parsePrimary(); + if (tok == Lexer.TokenType.EXCLAMATION || tok == Lexer.TokenType.MINUS) { + return parseUnaryOps(); + } + return parseMember(); + } + + private CelExpr parseMember() { + int memberStart = peekToken.start; + boolean startedWithIdentOrDot = + peekToken.type == Lexer.TokenType.DOT + || peekToken.type == Lexer.TokenType.IDENT + || peekToken.type == Lexer.TokenType.RESERVED_WORD; + CelExpr lhs = parsePrimary(); + boolean canBeStructName = + startedWithIdentOrDot + && (currentToken.type == Lexer.TokenType.IDENT + || currentToken.type == Lexer.TokenType.RESERVED_WORD) + && !isQuotedIdent(currentToken); currentLhsDepth = 0; - tok = peekToken.type; + Lexer.TokenType tok = peekToken.type; if (tok == Lexer.TokenType.DOT || tok == Lexer.TokenType.LEFT_BRACKET || tok == Lexer.TokenType.LEFT_BRACE) { - lhs = parseSelectorChainTail(lhs); + lhs = parseSelectorChainTail(lhs, memberStart, canBeStructName); } return lhs; } - private CelExpr parseSelectorChainTail(CelExpr initialLhs) { + private CelExpr parseSelectorChainTail( + CelExpr initialLhs, int memberStartPosition, boolean canBeStructName) { CelExpr lhs = initialLhs; int chainDepth = 0; while (true) { @@ -558,9 +572,7 @@ private CelExpr parseSelectorChainTail(CelExpr initialLhs) { } } Lexer.Token idTok = nextToken(); - if (idTok.type != Lexer.TokenType.IDENT - && idTok.type != Lexer.TokenType.RESERVED_WORD - && idTok.type != Lexer.TokenType.IN) { + if (idTok.type != Lexer.TokenType.IDENT && idTok.type != Lexer.TokenType.RESERVED_WORD) { if (idTok.type != Lexer.TokenType.ERROR) { reportSyntaxError(idTok, "expected identifier after '.'"); } @@ -570,11 +582,17 @@ private CelExpr parseSelectorChainTail(CelExpr initialLhs) { } boolean isMemberCall = (peekToken.type == Lexer.TokenType.LEFT_PAREN); String idText = normalizeIdent(idTok, /* allowQuoted= */ !isMemberCall); + if (idText.isEmpty()) { + synchronizeOnDelimiter(); + currentLhsDepth = chainDepth; + return ERROR; + } if (optional) { long opId = nextId(dotTok); CelExpr field = - CelExpr.ofConstant(nextId(getLeftmostPosition(lhs)), CelConstant.ofValue(idText)); + CelExpr.ofConstant(nextId(memberStartPosition), CelConstant.ofValue(idText)); lhs = buildBinaryCall(opId, Operator.OPTIONAL_SELECT.getFunction(), lhs, field); + canBeStructName = false; } else if (peekToken.type == Lexer.TokenType.LEFT_PAREN) { Lexer.Token lparen = nextToken(); long callId = nextId(lparen); @@ -584,8 +602,10 @@ private CelExpr parseSelectorChainTail(CelExpr initialLhs) { expanded.isPresent() ? expanded.get() : CelExpr.ofCall(callId, Optional.of(lhs), idText, args); + canBeStructName = false; } else { lhs = CelExpr.ofSelect(nextId(dotTok), lhs, idText, /* isTestOnly= */ false); + canBeStructName = canBeStructName && !isQuotedIdent(idTok); } } else if (tok == Lexer.TokenType.LEFT_BRACKET) { if (checkRecursion(chainDepth, peekToken)) { @@ -607,12 +627,17 @@ private CelExpr parseSelectorChainTail(CelExpr initialLhs) { String opName = optional ? Operator.OPTIONAL_INDEX.getFunction() : Operator.INDEX.getFunction(); lhs = buildBinaryCall(opId, opName, lhs, index); + canBeStructName = false; } else if (tok == Lexer.TokenType.LEFT_BRACE) { + if (!canBeStructName) { + break; + } String structName = extractStructName(lhs); if (structName == null) { break; } lhs = parseStruct(nextId(peekToken.start), structName); + canBeStructName = false; } else { break; } @@ -622,83 +647,42 @@ private CelExpr parseSelectorChainTail(CelExpr initialLhs) { } private CelExpr parseUnaryOps() { - Lexer.Token op = nextToken(); - Lexer.TokenType opType = op.type; - if (peekToken.type == Lexer.TokenType.EXCLAMATION || peekToken.type == Lexer.TokenType.MINUS) { - return parseUnaryOpsChain(op); - } - - if (opType == Lexer.TokenType.MINUS) { - if (peekToken.type == Lexer.TokenType.INT) { - return parseIntLiteral(nextId(peekToken), /* isNegative= */ true); - } - if (peekToken.type == Lexer.TokenType.FLOAT) { - return parseDoubleLiteral(nextId(peekToken), /* isNegative= */ true); - } - } - - if (checkRecursion(0, op)) { - return ERROR; - } - - long opId = nextId(op); - recursionDepth++; - CelExpr operand = parseSelectorChain(); - recursionDepth--; - if (recursionLimitExceeded) { - return ERROR; - } - - String opName = - (opType == Lexer.TokenType.EXCLAMATION) - ? Operator.LOGICAL_NOT.getFunction() - : Operator.NEGATE.getFunction(); - return buildUnaryCall(opId, opName, operand); - } - - private CelExpr parseUnaryOpsChain(Lexer.Token firstOp) { + Lexer.Token firstOp = nextToken(); + Lexer.TokenType opType = firstOp.type; List ops = new ArrayList<>(); ops.add(new UnaryOp(firstOp)); - while (peekToken.type == Lexer.TokenType.EXCLAMATION - || peekToken.type == Lexer.TokenType.MINUS) { + while (peekToken.type == opType) { ops.add(new UnaryOp(nextToken())); } - boolean hasSolitaryTrailingMinus = - !ops.isEmpty() - && Iterables.getLast(ops).token.type == Lexer.TokenType.MINUS - && (ops.size() == 1 || ops.get(ops.size() - 2).token.type != Lexer.TokenType.MINUS); - - if (!options.retainRepeatedUnaryOperators()) { - int write = 0; - for (int read = 0; read < ops.size(); ) { - int next = read; - while (next < ops.size() && ops.get(next).token.type == ops.get(read).token.type) { - next++; - } - if ((next - read) % 2 != 0) { - ops.set(write++, ops.get(read)); - } - read = next; + if (opType == Lexer.TokenType.MINUS + && ops.size() == 1 + && (peekToken.type == Lexer.TokenType.INT || peekToken.type == Lexer.TokenType.FLOAT)) { + CelExpr lhs = + (peekToken.type == Lexer.TokenType.INT) + ? parseIntLiteral(nextId(peekToken), /* isNegative= */ true) + : parseDoubleLiteral(nextId(peekToken), /* isNegative= */ true); + currentLhsDepth = 0; + Lexer.TokenType tok = peekToken.type; + if (tok == Lexer.TokenType.DOT + || tok == Lexer.TokenType.LEFT_BRACKET + || tok == Lexer.TokenType.LEFT_BRACE) { + lhs = parseSelectorChainTail(lhs, firstOp.start, /* canBeStructName= */ false); } - ops = new ArrayList<>(ops.subList(0, write)); - } - - for (UnaryOp op : ops) { - op.id = nextId(op.token); + return lhs; } - boolean isNegativeNumericLiteral = - hasSolitaryTrailingMinus - && (peekToken.type == Lexer.TokenType.INT || peekToken.type == Lexer.TokenType.FLOAT); - long negativeLiteralOpId = 0; - if (isNegativeNumericLiteral) { - negativeLiteralOpId = Iterables.getLast(ops).id; - ops.remove(ops.size() - 1); + if (!options.retainRepeatedUnaryOperators()) { + if (ops.size() % 2 == 0) { + ops.clear(); + } else { + ops = new ArrayList<>(ops.subList(0, 1)); + } } int chainDepth = 0; for (UnaryOp op : ops) { + op.id = nextId(op.token); if (checkRecursion(chainDepth, op.token)) { return ERROR; } @@ -707,14 +691,20 @@ private CelExpr parseUnaryOpsChain(Lexer.Token firstOp) { recursionDepth += ops.size(); CelExpr operand; - if (isNegativeNumericLiteral) { - operand = - (peekToken.type == Lexer.TokenType.INT) - ? parseIntLiteral(negativeLiteralOpId, /* isNegative= */ true) - : parseDoubleLiteral(negativeLiteralOpId, /* isNegative= */ true); - operand = parseSelectorChainTail(operand); + if (opType == Lexer.TokenType.EXCLAMATION && peekToken.type == Lexer.TokenType.MINUS) { + Lexer.Token minusTok = nextToken(); + if (peekToken.type == Lexer.TokenType.INT) { + operand = parseIntLiteral(nextId(peekToken), /* isNegative= */ true); + operand = parseSelectorChainTail(operand, minusTok.start, /* canBeStructName= */ false); + } else if (peekToken.type == Lexer.TokenType.FLOAT) { + operand = parseDoubleLiteral(nextId(peekToken), /* isNegative= */ true); + operand = parseSelectorChainTail(operand, minusTok.start, /* canBeStructName= */ false); + } else { + reportSyntaxError(minusTok, "unexpected '-'"); + operand = parseMember(); + } } else { - operand = parseSelectorChain(); + operand = parseMember(); } recursionDepth -= ops.size(); @@ -1044,6 +1034,13 @@ private String normalizeIdent(Lexer.Token tok, boolean allowQuoted) { return text; } + private boolean isQuotedIdent(Lexer.Token tok) { + if (tok.text != null) { + return !tok.text.isEmpty() && tok.text.charAt(0) == '`'; + } + return tok.start >= 0 && tok.start < tok.end && content.get(tok.start) == '`'; + } + private static boolean isAsciiAlphanumeric(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } @@ -1066,13 +1063,6 @@ private static boolean isAsciiAlphanumeric(char c) { return null; } - private int getLeftmostPosition(CelExpr expr) { - while (expr.exprKind().getKind() == CelExpr.ExprKind.Kind.SELECT) { - expr = expr.select().operand(); - } - return getPosition(expr.id()); - } - private @Nullable CelMacro lookupMacro(String id, int argCount, boolean receiverStyle) { if (macros.isEmpty()) { return null; @@ -1188,7 +1178,7 @@ private int countGroupingParentheses() { int size = content.size(); while (pos < size) { int c = content.get(pos); - if (c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f' && c != 11) { + if (c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f') { if (c == '/') { // A comment might precede another '('. break; diff --git a/parser/src/test/java/dev/cel/parser/CelParserParameterizedTest.java b/parser/src/test/java/dev/cel/parser/CelParserParameterizedTest.java index 72ba9aab8..0b3a38bba 100644 --- a/parser/src/test/java/dev/cel/parser/CelParserParameterizedTest.java +++ b/parser/src/test/java/dev/cel/parser/CelParserParameterizedTest.java @@ -300,6 +300,7 @@ public void parser_core_syntax() { runTest("a.b"); runTest("a.b.c"); runTest("a.?b"); + runTest("a.?b.?c"); runTest("a.`b-c`"); runTest("a.`b c`"); runTest("a.`b.c`"); @@ -330,6 +331,8 @@ public void parser_core_syntax() { runTest("! false"); runTest("-a"); runTest("---a"); + runTest("!-42"); + runTest("!-4.2"); // Arithmetic operators runTest("x * 2"); @@ -355,6 +358,7 @@ public void parser_core_syntax() { runTest("a > b"); runTest("a >= b"); runTest("a in b"); + runTest("9in-x"); runTest("\"\ud83d\ude01\" in [\"\ud83d\ude01\", \"\ud83d\ude11\", \"\ud83d\ude26\"]"); runTest("size(x) == x.size()"); runTest("x.single_nested_message != null"); @@ -375,7 +379,7 @@ public void parser_core_syntax() { runTest("cond ? 1 : 2"); runTest("false && !true || false ? 2 : 3"); runTest(OPTIONS_MAX_RECURSION_DEPTH_32, Strings.repeat("true ? 1 : ", 31) + "1", false); - runAntlrTest(OPTIONS_MAX_RECURSION_DEPTH_32, Strings.repeat("!-", 15) + "x"); + runTest(OPTIONS_MAX_RECURSION_DEPTH_32, Strings.repeat("!-", 15) + "x", false); // Complex expressions runTest("1 + 2 * 3 - 1 / 2 == 6 % 1"); @@ -451,6 +455,7 @@ public void parser_errors() { runTest("*@a | b"); runTest("((@))"); runTest("1 + $"); + runTest("1 \u000b + 2"); runTest( "\u00f3\u00a0\u00a2\n" + "\t\t\u00f3\u00a00\u00a0\n" @@ -464,6 +469,8 @@ public void parser_errors() { // Unexpected tokens runTest("1 + +"); + runTest("-!x"); + runTest("!-x"); runTest("?"); runTest("a ? b ((?))"); runTest("a ? b @"); @@ -543,6 +550,7 @@ public void parser_errors() { // Member selection errors runTest("{\"a\": 1}.\"a\""); runTest("self.true == 1"); + runTest("a.in"); // Map syntax errors runTest("{a}"); @@ -556,6 +564,11 @@ public void parser_errors() { runTest("x{."); runTest("t{>C}"); runTest("has([(has(("); + runTest("(a){}"); + runTest("(a.b){}"); + runTest("(a).b{}"); + runTest("a.`b-c`{}"); + runTest("Msg{`$b`: 1}"); // Macro errors runTest("1.all(2, 3)"); @@ -590,6 +603,7 @@ public void parser_errors() { runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "`b-c`"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "`b-c`()"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "a.`$b`"); + runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "has(a.`$b`)"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "a.`b.c`()"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "`bar`"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "foo.``"); diff --git a/parser/src/test/java/dev/cel/parser/PrattParserTest.java b/parser/src/test/java/dev/cel/parser/PrattParserTest.java index 710ff2fcf..666992fb1 100644 --- a/parser/src/test/java/dev/cel/parser/PrattParserTest.java +++ b/parser/src/test/java/dev/cel/parser/PrattParserTest.java @@ -93,8 +93,10 @@ public void pratt_parser_literals() { runTest("0"); runTest("42"); runTest("0xF"); + runTest("0X12"); runTest("0x2A"); runTest("-1"); + runTest("-0X12"); runTest("-42"); runTest("0xFFFFFFFFFFFFFFFFF"); runTest("9223372036854775807"); // Long.MAX_VALUE @@ -106,6 +108,7 @@ public void pratt_parser_literals() { runTest("0u"); runTest("23u"); runTest("0xFu"); + runTest("0XFu"); runTest("0xFFFFFFFFFFFFFFFFFu"); runTest("123u_"); @@ -229,6 +232,7 @@ public void pratt_parser_core_syntax() { runTest("a.b"); runTest("a.b.c"); runTest("a.?b"); + runTest("a.?b.?c"); runTest("a.`b-c`"); runTest("a.`b c`"); runTest("a.`b.c`"); @@ -257,6 +261,8 @@ public void pratt_parser_core_syntax() { runTest("!x"); runTest("! false"); runTest("-a"); + runTest("!-42"); + runTest("!-4.2"); // Arithmetic operators runTest("x * 2"); @@ -282,6 +288,7 @@ public void pratt_parser_core_syntax() { runTest("a > b"); runTest("a >= b"); runTest("a in b"); + runTest("9in-x"); runTest("\"\ud83d\ude01\" in [\"\ud83d\ude01\", \"\ud83d\ude11\", \"\ud83d\ude26\"]"); runTest("size(x) == x.size()"); runTest("x.single_nested_message != null"); @@ -358,6 +365,7 @@ public void pratt_parser_errors() { runTest("*@a | b"); runTest("((@))"); runTest("1 + $"); + runTest("1 \u000b + 2"); runTest( "\u00f3\u00a0\u00a2\n" + "\t\t\u00f3\u00a00\u00a0\n" @@ -368,6 +376,8 @@ public void pratt_parser_errors() { // Unexpected tokens runTest("1 + +"); + runTest("-!x"); + runTest("!-x"); runTest("?"); runTest("a ? b ((?))"); runTest("a ? b @"); @@ -427,6 +437,7 @@ public void pratt_parser_errors() { // Member selection errors runTest("{\"a\": 1}.\"a\""); runTest("self.true == 1"); + runTest("a.in"); // Map syntax errors runTest("{a}"); @@ -438,6 +449,11 @@ public void pratt_parser_errors() { runTest("ind[a{b}]"); runTest("x{?."); runTest("x{."); + runTest("(a){}"); + runTest("(a.b){}"); + runTest("(a).b{}"); + runTest("a.`b-c`{}"); + runTest("Msg{`$b`: 1}"); // Macro errors runTest("1.all(2, 3)"); @@ -458,6 +474,7 @@ public void pratt_parser_errors() { runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "`b-c`"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "`b-c`()"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "a.`$b`"); + runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "has(a.`$b`)"); runTest(OPTIONS_QUOTED_IDENTIFIER_SYNTAX, "a.`b.c`()"); // Recursion limit exceeded diff --git a/parser/src/test/resources/parser_core_syntax.baseline b/parser/src/test/resources/parser_core_syntax.baseline index 34997c9d8..4e853dee2 100644 --- a/parser/src/test/resources/parser_core_syntax.baseline +++ b/parser/src/test/resources/parser_core_syntax.baseline @@ -347,6 +347,23 @@ L: _?._( "b"^#3[1,0]# )^#2[1,1]# +I: a.?b.?c +=====> +P: _?._( + _?._( + a^#1:Expr.Ident#, + "b"^#3:string# + )^#2:Expr.Call#, + "c"^#5:string# +)^#4:Expr.Call# +L: _?._( + _?._( + a^#1[1,0]#, + "b"^#3[1,0]# + )^#2[1,1]#, + "c"^#5[1,0]# +)^#4[1,4]# + I: a.`b-c` =====> P: a^#1:Expr.Ident#.b-c^#2:Expr.Select# @@ -553,6 +570,24 @@ L: -_( a^#2[1,3]# )^#1[1,0]# +I: !-42 +=====> +P: !_( + -42^#2:int64# +)^#1:Expr.Call# +L: !_( + -42^#2[1,2]# +)^#1[1,0]# + +I: !-4.2 +=====> +P: !_( + -4.2^#2:double# +)^#1:Expr.Call# +L: !_( + -4.2^#2[1,2]# +)^#1[1,0]# + I: x * 2 =====> P: _*_( @@ -808,6 +843,21 @@ L: @in( b^#3[1,5]# )^#2[1,2]# +I: 9in-x +=====> +P: @in( + 9^#1:int64#, + -_( + x^#4:Expr.Ident# + )^#3:Expr.Call# +)^#2:Expr.Call# +L: @in( + 9^#1[1,0]#, + -_( + x^#4[1,4]# + )^#3[1,3]# +)^#2[1,1]# + I: "😁" in ["😁", "😑", "😦"] =====> P: @in( @@ -1237,6 +1287,51 @@ ERROR: :1:29: no viable alternative at input '-!' ERROR: :1:31: no viable alternative at input '-x' | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x | ..............................^ +E/P: ERROR: :1:2: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .^ +ERROR: :1:3: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..^ +ERROR: :1:6: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .....^ +ERROR: :1:7: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ......^ +ERROR: :1:10: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .........^ +ERROR: :1:11: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..........^ +ERROR: :1:14: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .............^ +ERROR: :1:15: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..............^ +ERROR: :1:18: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .................^ +ERROR: :1:19: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..................^ +ERROR: :1:22: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .....................^ +ERROR: :1:23: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ......................^ +ERROR: :1:26: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .........................^ +ERROR: :1:27: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..........................^ +ERROR: :1:30: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .............................^ I: 1 + 2 * 3 - 1 / 2 == 6 % 1 =====> @@ -1431,4 +1526,4 @@ P: Struct{ }^#1:Expr.CreateStruct# L: Struct{ in:false^#3[1,13]#^#2[1,11]# -}^#1[1,6]# \ No newline at end of file +}^#1[1,6]# diff --git a/parser/src/test/resources/parser_errors.baseline b/parser/src/test/resources/parser_errors.baseline index cbd9f087b..eee7aae4a 100644 --- a/parser/src/test/resources/parser_errors.baseline +++ b/parser/src/test/resources/parser_errors.baseline @@ -43,6 +43,15 @@ E/P: ERROR: :1:5: Syntax error: unexpected character | 1 + $ | ....^ +I: 1 + 2 +=====> +E/A: ERROR: :1:3: token recognition error at: ' ' + | 1 + 2 + | ..^ +E/P: ERROR: :1:3: Syntax error: unexpected character + | 1 + 2 + | ..^ + I: ó ¢ »»ó 0  »»\u007f0"""\""\"""\""\"""\""\"""\""\"""\"\"""\""\"""\""\"""\""\"""\"!\"""\""\"""\""\" @@ -186,6 +195,27 @@ E/P: ERROR: :1:5: Syntax error: unexpected token | 1 + + | ....^ +I: -!x +=====> +E/A: ERROR: :1:2: no viable alternative at input '-!' + | -!x + | .^ +E/P: ERROR: :1:2: Syntax error: unexpected token + | -!x + | .^ +ERROR: :1:3: Syntax error: unexpected token after expression + | -!x + | ..^ + +I: !-x +=====> +E/A: ERROR: :1:3: no viable alternative at input '-x' + | !-x + | ..^ +E/P: ERROR: :1:2: Syntax error: unexpected '-' + | !-x + | .^ + I: ? =====> E/A: ERROR: :1:1: mismatched input '?' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} @@ -645,6 +675,18 @@ E/P: ERROR: :1:6: Syntax error: expected identifier after '.' | self.true == 1 | .....^ +I: a.in +=====> +E/A: ERROR: :1:3: no viable alternative at input '.in' + | a.in + | ..^ +ERROR: :1:5: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | a.in + | ....^ +E/P: ERROR: :1:3: Syntax error: expected identifier after '.' + | a.in + | ..^ + I: {a} =====> E/A: ERROR: :1:3: mismatched input '}' expecting {'==', '!=', 'in', '<', '<=', '>=', '>', '&&', '||', '[', '.', '-', '?', ':', '+', '*', '/', '%%'} @@ -780,6 +822,57 @@ ERROR: :1:12: Syntax error: mismatched input expecting ')' | has([(has(( | ...........^ +I: (a){} +=====> +E/A: ERROR: :1:4: mismatched input '{' expecting {'==', '!=', 'in', '<', '<=', '>=', '>', '&&', '||', '[', ')', '.', '-', '?', '+', '*', '/', '%%'} + | (a){} + | ...^ +E/P: ERROR: :1:4: Syntax error: unexpected token after expression + | (a){} + | ...^ + +I: (a.b){} +=====> +E/A: ERROR: :1:6: mismatched input '{' expecting {'==', '!=', 'in', '<', '<=', '>=', '>', '&&', '||', '[', ')', '.', '-', '?', '+', '*', '/', '%%'} + | (a.b){} + | .....^ +E/P: ERROR: :1:6: Syntax error: unexpected token after expression + | (a.b){} + | .....^ + +I: (a).b{} +=====> +E/A: ERROR: :1:6: mismatched input '{' expecting {, '==', '!=', 'in', '<', '<=', '>=', '>', '&&', '||', '[', '.', '-', '?', '+', '*', '/', '%%'} + | (a).b{} + | .....^ +E/P: ERROR: :1:6: Syntax error: unexpected token after expression + | (a).b{} + | .....^ + +I: a.`b-c`{} +=====> +E/A: ERROR: :1:8: mismatched input '{' expecting {, '==', '!=', 'in', '<', '<=', '>=', '>', '&&', '||', '[', '.', '-', '?', '+', '*', '/', '%%'} + | a.`b-c`{} + | .......^ +E/P: ERROR: :1:8: Syntax error: unexpected token after expression + | a.`b-c`{} + | .......^ + +I: Msg{`$b`: 1} +=====> +E/A: ERROR: :1:5: token recognition error at: '`$' + | Msg{`$b`: 1} + | ....^ +ERROR: :1:8: token recognition error at: '`:' + | Msg{`$b`: 1} + | .......^ +ERROR: :1:11: missing ':' at '1' + | Msg{`$b`: 1} + | ..........^ +E/P: ERROR: :1:5: unexpected quoted identifier + | Msg{`$b`: 1} + | ....^ + I: 1.all(2, 3) =====> E/A: ERROR: :1:7: The argument must be a simple name @@ -1050,6 +1143,21 @@ E/P: ERROR: :1:3: unexpected quoted identifier | a.`$b` | ..^ +I: has(a.`$b`) +=====> +E/A: ERROR: :1:7: token recognition error at: '`$' + | has(a.`$b`) + | ......^ +ERROR: :1:10: token recognition error at: '`)' + | has(a.`$b`) + | .........^ +ERROR: :1:12: missing ')' at '' + | has(a.`$b`) + | ...........^ +E/P: ERROR: :1:7: unexpected quoted identifier + | has(a.`$b`) + | ......^ + I: a.`b.c`() =====> E/A: ERROR: :1:8: mismatched input '(' expecting {, '==', '!=', 'in', '<', '<=', '>=', '>', '&&', '||', '[', '.', '-', '?', '+', '*', '/', '%%'} @@ -1058,6 +1166,9 @@ E/A: ERROR: :1:8: mismatched input '(' expecting {, '==', '!=', 'in' E/P: ERROR: :1:3: unexpected quoted identifier | a.`b.c`() | ..^ +ERROR: :1:9: Syntax error: unexpected token after expression + | a.`b.c`() + | ........^ I: `bar` =====> @@ -1248,9 +1359,54 @@ ERROR: :1:31: no viable alternative at input '-!' ERROR: :1:33: no viable alternative at input '-!' | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x | ................................^ -E/P: ERROR: :1:33: Expression recursion limit exceeded. limit: 32 +E/P: ERROR: :1:2: Syntax error: unexpected '-' | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x - | ................................^ + | .^ +ERROR: :1:3: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..^ +ERROR: :1:6: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .....^ +ERROR: :1:7: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ......^ +ERROR: :1:10: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .........^ +ERROR: :1:11: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..........^ +ERROR: :1:14: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .............^ +ERROR: :1:15: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..............^ +ERROR: :1:18: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .................^ +ERROR: :1:19: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..................^ +ERROR: :1:22: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .....................^ +ERROR: :1:23: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ......................^ +ERROR: :1:26: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .........................^ +ERROR: :1:27: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..........................^ +ERROR: :1:30: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .............................^ +ERROR: :1:31: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..............................^ I: 123456 =====> @@ -1287,4 +1443,4 @@ E/P: ERROR: :1:4: Syntax error: expected ']' | ...^ ERROR: :1:13: Syntax error: unexpected token after expression | [1 2 3 a b c] - | ............^ \ No newline at end of file + | ............^ diff --git a/parser/src/test/resources/parser_literals.baseline b/parser/src/test/resources/parser_literals.baseline index f4716e927..e0139c99d 100644 --- a/parser/src/test/resources/parser_literals.baseline +++ b/parser/src/test/resources/parser_literals.baseline @@ -76,9 +76,9 @@ I: 123a E/A: ERROR: :1:4: extraneous input 'a' expecting | 123a | ...^ -E/P: ERROR: :1:1: Syntax error: int literal has unexpected trailing characters +E/P: ERROR: :1:4: Syntax error: unexpected token after expression | 123a - | ^ + | ...^ I: 0u =====> @@ -129,9 +129,9 @@ I: 123u_ E/A: ERROR: :1:5: extraneous input '_' expecting | 123u_ | ....^ -E/P: ERROR: :1:1: Syntax error: uint literal has unexpected trailing characters +E/P: ERROR: :1:5: Syntax error: unexpected token after expression | 123u_ - | ^ + | ....^ I: 3.14 =====> @@ -245,9 +245,9 @@ I: 0x123z E/A: ERROR: :1:6: extraneous input 'z' expecting | 0x123z | .....^ -E/P: ERROR: :1:1: Syntax error: int literal has unexpected trailing characters +E/P: ERROR: :1:6: Syntax error: unexpected token after expression | 0x123z - | ^ + | .....^ I: 'hello' =====> diff --git a/parser/src/test/resources/pratt_parser_core_syntax.baseline b/parser/src/test/resources/pratt_parser_core_syntax.baseline index fb9d94e58..6afc4e162 100644 --- a/parser/src/test/resources/pratt_parser_core_syntax.baseline +++ b/parser/src/test/resources/pratt_parser_core_syntax.baseline @@ -347,6 +347,23 @@ L: _?._( "b"^#3[1,0]# )^#2[1,1]# +I: a.?b.?c +=====> +P: _?._( + _?._( + a^#1:Expr.Ident#, + "b"^#3:string# + )^#2:Expr.Call#, + "c"^#5:string# +)^#4:Expr.Call# +L: _?._( + _?._( + a^#1[1,0]#, + "b"^#3[1,0]# + )^#2[1,1]#, + "c"^#5[1,0]# +)^#4[1,4]# + I: a.`b-c` =====> P: a^#1:Expr.Ident#.b-c^#2:Expr.Select# @@ -535,6 +552,24 @@ L: -_( a^#2[1,1]# )^#1[1,0]# +I: !-42 +=====> +P: !_( + -42^#2:int64# +)^#1:Expr.Call# +L: !_( + -42^#2[1,2]# +)^#1[1,0]# + +I: !-4.2 +=====> +P: !_( + -4.2^#2:double# +)^#1:Expr.Call# +L: !_( + -4.2^#2[1,2]# +)^#1[1,0]# + I: x * 2 =====> P: _*_( @@ -790,6 +825,21 @@ L: @in( b^#3[1,5]# )^#2[1,2]# +I: 9in-x +=====> +P: @in( + 9^#1:int64#, + -_( + x^#4:Expr.Ident# + )^#3:Expr.Call# +)^#2:Expr.Call# +L: @in( + 9^#1[1,0]#, + -_( + x^#4[1,4]# + )^#3[1,3]# +)^#2[1,1]# + I: "😁" in ["😁", "😑", "😦"] =====> P: @in( @@ -1174,6 +1224,51 @@ I: true ? 1 : true ? 1 : true ? 1 : true ? 1 : true ? 1 : true ? 1 : true ? 1 : I: !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x =====> +E: ERROR: :1:2: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .^ +ERROR: :1:3: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..^ +ERROR: :1:6: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .....^ +ERROR: :1:7: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ......^ +ERROR: :1:10: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .........^ +ERROR: :1:11: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..........^ +ERROR: :1:14: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .............^ +ERROR: :1:15: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..............^ +ERROR: :1:18: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .................^ +ERROR: :1:19: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..................^ +ERROR: :1:22: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .....................^ +ERROR: :1:23: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ......................^ +ERROR: :1:26: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .........................^ +ERROR: :1:27: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | ..........................^ +ERROR: :1:30: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-x + | .............................^ I: 1 + 2 * 3 - 1 / 2 == 6 % 1 =====> @@ -1310,4 +1405,4 @@ P: [ L: [ 1^#2[2,2]#, 2^#3[3,2]# -]^#1[1,0]# \ No newline at end of file +]^#1[1,0]# diff --git a/parser/src/test/resources/pratt_parser_errors.baseline b/parser/src/test/resources/pratt_parser_errors.baseline index d21e65ab3..f2ac5cf6d 100644 --- a/parser/src/test/resources/pratt_parser_errors.baseline +++ b/parser/src/test/resources/pratt_parser_errors.baseline @@ -19,6 +19,12 @@ E: ERROR: :1:5: Syntax error: unexpected character | 1 + $ | ....^ +I: 1 + 2 +=====> +E: ERROR: :1:3: Syntax error: unexpected character + | 1 + 2 + | ..^ + I: ó ¢ »»ó 0  »»\u007f0"""\""\"""\""\"""\""\"""\""\"""\"\"""\""\"""\""\"""\""\"""\"!\"""\""\"""\""\" @@ -54,6 +60,21 @@ E: ERROR: :1:5: Syntax error: unexpected token | 1 + + | ....^ +I: -!x +=====> +E: ERROR: :1:2: Syntax error: unexpected token + | -!x + | .^ +ERROR: :1:3: Syntax error: unexpected token after expression + | -!x + | ..^ + +I: !-x +=====> +E: ERROR: :1:2: Syntax error: unexpected '-' + | !-x + | .^ + I: ? =====> E: ERROR: :1:1: Syntax error: unexpected token @@ -250,6 +271,12 @@ E: ERROR: :1:6: Syntax error: expected identifier after '.' | self.true == 1 | .....^ +I: a.in +=====> +E: ERROR: :1:3: Syntax error: expected identifier after '.' + | a.in + | ..^ + I: {a} =====> E: ERROR: :1:3: Syntax error: expected ':' in map entry @@ -304,6 +331,36 @@ ERROR: :1:4: Syntax error: expected '}' | x{. | ...^ +I: (a){} +=====> +E: ERROR: :1:4: Syntax error: unexpected token after expression + | (a){} + | ...^ + +I: (a.b){} +=====> +E: ERROR: :1:6: Syntax error: unexpected token after expression + | (a.b){} + | .....^ + +I: (a).b{} +=====> +E: ERROR: :1:6: Syntax error: unexpected token after expression + | (a).b{} + | .....^ + +I: a.`b-c`{} +=====> +E: ERROR: :1:8: Syntax error: unexpected token after expression + | a.`b-c`{} + | .......^ + +I: Msg{`$b`: 1} +=====> +E: ERROR: :1:5: unexpected quoted identifier + | Msg{`$b`: 1} + | ....^ + I: 1.all(2, 3) =====> E: ERROR: :1:7: The argument must be a simple name @@ -385,11 +442,20 @@ E: ERROR: :1:3: unexpected quoted identifier | a.`$b` | ..^ +I: has(a.`$b`) +=====> +E: ERROR: :1:7: unexpected quoted identifier + | has(a.`$b`) + | ......^ + I: a.`b.c`() =====> E: ERROR: :1:3: unexpected quoted identifier | a.`b.c`() | ..^ +ERROR: :1:9: Syntax error: unexpected token after expression + | a.`b.c`() + | ........^ I: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ »»»[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['too many']]]]]]]]]]]]]]]]]]]]]]]]]]]] @@ -480,9 +546,54 @@ E: ERROR: :1:353: Expression recursion limit exceeded. limit: 32 I: !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x =====> -E: ERROR: :1:33: Expression recursion limit exceeded. limit: 32 +E: ERROR: :1:2: Syntax error: unexpected '-' | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x - | ................................^ + | .^ +ERROR: :1:3: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..^ +ERROR: :1:6: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .....^ +ERROR: :1:7: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ......^ +ERROR: :1:10: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .........^ +ERROR: :1:11: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..........^ +ERROR: :1:14: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .............^ +ERROR: :1:15: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..............^ +ERROR: :1:18: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .................^ +ERROR: :1:19: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..................^ +ERROR: :1:22: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .....................^ +ERROR: :1:23: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ......................^ +ERROR: :1:26: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .........................^ +ERROR: :1:27: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..........................^ +ERROR: :1:30: Syntax error: unexpected '-' + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | .............................^ +ERROR: :1:31: Syntax error: unexpected token + | !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!x + | ..............................^ I: 123456 =====> @@ -511,4 +622,4 @@ E: ERROR: :1:4: Syntax error: expected ']' | ...^ ERROR: :1:13: Syntax error: unexpected token after expression | [1 2 3 a b c] - | ............^ \ No newline at end of file + | ............^ diff --git a/parser/src/test/resources/pratt_parser_literals.baseline b/parser/src/test/resources/pratt_parser_literals.baseline index f6ce2f6b0..74002373b 100644 --- a/parser/src/test/resources/pratt_parser_literals.baseline +++ b/parser/src/test/resources/pratt_parser_literals.baseline @@ -28,6 +28,11 @@ I: 0xF P: 15^#1:int64# L: 15^#1[1,0]# +I: 0X12 +=====> +P: 18^#1:int64# +L: 18^#1[1,0]# + I: 0x2A =====> P: 42^#1:int64# @@ -38,6 +43,11 @@ I: -1 P: -1^#1:int64# L: -1^#1[1,1]# +I: -0X12 +=====> +P: -18^#1:int64# +L: -18^#1[1,1]# + I: -42 =====> P: -42^#1:int64# @@ -67,9 +77,9 @@ E: ERROR: :1:3: Syntax error: invalid int literal: 9223372036854775808 I: 123a =====> -E: ERROR: :1:1: Syntax error: int literal has unexpected trailing characters +E: ERROR: :1:4: Syntax error: unexpected token after expression | 123a - | ^ + | ...^ I: 0u =====> @@ -86,6 +96,11 @@ I: 0xFu P: 15u^#1:uint64# L: 15u^#1[1,0]# +I: 0XFu +=====> +P: 15u^#1:uint64# +L: 15u^#1[1,0]# + I: 0xFFFFFFFFFFFFFFFFFu =====> E: ERROR: :1:1: Syntax error: invalid uint literal: 0xFFFFFFFFFFFFFFFFFu @@ -94,9 +109,9 @@ E: ERROR: :1:1: Syntax error: invalid uint literal: 0xFFFFFFFFFFFFFFFFFu I: 123u_ =====> -E: ERROR: :1:1: Syntax error: uint literal has unexpected trailing characters +E: ERROR: :1:5: Syntax error: unexpected token after expression | 123u_ - | ^ + | ....^ I: 3.14 =====> @@ -183,9 +198,9 @@ E: ERROR: :1:3: Syntax error: floating point literal missing digits after I: 0x123z =====> -E: ERROR: :1:1: Syntax error: int literal has unexpected trailing characters +E: ERROR: :1:6: Syntax error: unexpected token after expression | 0x123z - | ^ + | .....^ I: 'hello' =====>