ANTLR4自定义表达式语法无法解析指定表达式,应如何修复?
你提供的测试表达式为:
differenceInDays(new Date(1999, 10,1), true ? new Date(1999, 10,2) : "A")>3
收到的报错为:
ExpressionsParserGrammar::expression:1:72: extraneous input ')' expecting {, '?', '||', '&&', '+', '-', '*', '/', '=', '!', '==', '!=', '>', '<', '>=', '<='}
错误原因
你当前的语法存在两处核心问题:
- 时间差函数规则缺漏右括号匹配:
DIFFERENCE_IN_DAYS、DIFFERENCE_IN_HOURS、DIFFERENCE_IN_MINUTES三个函数的语法规则定义时,只写了左括号和参数,没有匹配结尾的右括号),所以当解析到函数参数后的)时,识别为非法的多余输入,这是你收到报错的直接原因。 - 运算符优先级排序错误:当前规则把全等/比较运算、三目运算的优先级放在了加减乘除运算之前,不符合通用表达式的运算逻辑,后续解析带混合运算的表达式时会出现逻辑错误。通用表达式优先级从高到低的顺序为:括号/函数调用 → 一元运算 → 乘除 → 加减 → 大小比较 → 相等/全等判断 → 逻辑与 → 逻辑或 → 三目运算。
修复方案
你只需要调整expression规则的优先级顺序,同时给三个时间差函数补上右括号匹配即可,修改后的核心规则如下:
grammar ExpressionsParserGrammar; expression // 最高优先级放在最前面 : LPAREN expr = expression RPAREN # brackets_expr | NOT expr = expression # not_expr // 函数调用类 | POWER_FUNC LPAREN expr1 = expression COMMA expr2 = expression RPAREN # power_expr | LAST_VAL_FUNC LPAREN last_str_func = STRING_VALUE (COMMA config = STRING_VALUE)? RPAREN # last_val_func | LAST_STR_FUNC LPAREN last_str_func = STRING_VALUE RPAREN # last_str_func | SUBMISSION_VAL_FUNC LPAREN sumission_val_str = STRING_VALUE RPAREN # submission_val_func | SUBMISSION_STR_FUNC LPAREN submission_str = STRING_VALUE RPAREN # submission_str_func | DATE_FORMAT_FUNC LPAREN date_format_expr = expression COMMA formatParam = STRING_VALUE RPAREN # date_format_func | NEW DATE LPAREN (expr = expression (COMMA expr = expression)*)? RPAREN # date // 修复:时间差函数补上右括号 | DIFFERENCE_IN_HOURS LPAREN left = expression COMMA right = expression RPAREN # dif_in_hours | DIFFERENCE_IN_DAYS LPAREN left = expression COMMA right = expression RPAREN # dif_in_days | DIFFERENCE_IN_MINUTES LPAREN left = expression COMMA right = expression RPAREN # dif_in_minutes | DATE_ADD LPAREN date = expression COMMA d=duration RPAREN # dateAddFunc | DATE_SUBTRACT LPAREN date = expression COMMA d=duration RPAREN # dateSubtractFunc | NOW LPAREN RPAREN # now // 字面量 | numLiteral = NUMBER_LITERAL # process_number | strValueLiteral = STRING_VALUE # process_str | boolLiteral = (TRUE | FALSE) # process_bool // 乘除 | left = expression mul_or_div = (MUL | DIV) right = expression # mul_div_expr // 加减 | left = expression plus_minus = (PLUS | MINUS) right = expression # add_expr // 大小比较 | left = expression equality_operation = (MORE_THAN | LESS | MORE_OR_EQUALS | LESS_OR_EQUALS) right = expression # equality_operation // 相等/全等判断 | left = expression identity_operation = (IDENTITY | NOT_IDENTITY | EQUALS | NOT_EQUALS) right = expression # identity_operation // 逻辑与 | left = expression AND right = expression # and_expr // 逻辑或 | left = expression OR right = expression # or_expr // 最低优先级:三目运算 | condition = expression '?' left = expression COLON right = expression # question_expr ; duration:L_CURLY_BRACE (YEARS COLON years = expression) ( COMMA MONTHS COLON months = expression)? (COMMA WEEKS COLON weeks = expression )? (COMMA DAYS COLON days = expression )? ( COMMA HOURS COLON hours = expression )? ( COMMA MINUTES COLON minutes = expression )? (COMMA SECONDS COLON seconds = expression)? R_CURLY_BRACE; SECONDS: 'seconds'; MINUTES: 'minutes' ; HOURS:'hours'; DAYS:'days'; WEEKS:'weeks'; MONTHS:'months'; YEARS:'years'; OR:'||'; AND:'&&'; NOT:'!'; DIFFERENCE_IN_MINUTES:'differenceInMinutes'; DIFFERENCE_IN_DAYS:'differenceInDays'; DIFFERENCE_IN_HOURS:'differenceInHours'; DATE_ADD:'dateAdd'; DATE_SUBTRACT:'dateSubtract'; COLON:':'; NOW:'now'; NEW:'new'; DATE:'Date'; PLUS:'+'; MINUS:'-'; MUL:'*'; DIV:'/'; LPAREN:'('; RPAREN:')'; NUMBER_LITERAL:'0'|[1-9][0-9]*; IDENTITY:'==='; NOT_IDENTITY:'!=='; EQUALS:'=='; NOT_EQUALS:'!='; MORE_THAN:'>'; LESS:'<'; MORE_OR_EQUALS:'>='; LESS_OR_EQUALS:'<='; LAST_VAL_FUNC:'lastVal'; LAST_STR_FUNC:'lastStr'; SUBMISSION_VAL_FUNC:'submissionVal'; SUBMISSION_STR_FUNC:'submissionStr'; POWER_FUNC:'power'; DATE_FORMAT_FUNC:'dateFormat'; COMMA:','; L_CURLY_BRACE:'{'; R_CURLY_BRACE:'}'; TRUE:'true'; FALSE:'false'; STRING_VALUE:'"'('\\"'|.)*?'"'; WS:[ \r\t\n]+ -> skip;
修改后你提供的测试表达式即可正常解析,不会再报括号相关的错误,同时混合运算的优先级逻辑也符合通用预期。
内容的提问来源于stack exchange,提问作者Vladimir Kozhaev
相关产品推荐
相关产品推荐

