You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ANTLR4自定义表达式语法无法解析指定表达式,应如何修复?

你提供的测试表达式为:

differenceInDays(new Date(1999, 10,1), true ? new Date(1999, 10,2) : "A")>3

收到的报错为:

ExpressionsParserGrammar::expression:1:72: extraneous input ')' expecting {, '?', '||', '&&', '+', '-', '*', '/', '=', '!', '==', '!=', '>', '<', '>=', '<='}


错误原因

你当前的语法存在两处核心问题:

  1. 时间差函数规则缺漏右括号匹配:DIFFERENCE_IN_DAYS、DIFFERENCE_IN_HOURS、DIFFERENCE_IN_MINUTES三个函数的语法规则定义时,只写了左括号和参数,没有匹配结尾的右括号),所以当解析到函数参数后的)时,识别为非法的多余输入,这是你收到报错的直接原因。
  2. 运算符优先级排序错误:当前规则把全等/比较运算、三目运算的优先级放在了加减乘除运算之前,不符合通用表达式的运算逻辑,后续解析带混合运算的表达式时会出现逻辑错误。通用表达式优先级从高到低的顺序为:括号/函数调用 → 一元运算 → 乘除 → 加减 → 大小比较 → 相等/全等判断 → 逻辑与 → 逻辑或 → 三目运算。

修复方案

你只需要调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 22:45:05