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

Antlr4自定义SpringEL风格表达式语法:如何让Parser检测出非法数字(如3ww)的语法错误?

解决Antlr4无法检测非法数字后缀的问题

嘿,这个问题我之前帮人排查过类似的!核心原因是你的解析器只匹配了输入的前缀部分,没有验证整个输入是否完全符合语法,再加上原语法规则的结构让解析器错误地把3ww拆成了合法的Integer(3)和Identifier(ww),完全没意识到这是个非法的整体。

问题根源

你碰到的场景:

  • 合法输入#user.age>3能正常解析
  • 非法输入#user.age>3ww或#user.age>3ww && #user.age<2却没报错

这是因为原语法的statement规则只要求匹配一个expr,但没有强制匹配到输入的末尾(EOF),所以解析器匹配完#user.age>3就停止了,直接忽略后面的ww,自然不会触发错误。

修改后的完整语法规则

下面是调整后的代码,关键修改点我会逐一说明:

grammar FlowExpr;

// 核心修改:强制匹配整个输入到末尾,非法后缀会直接触发错误
statement : expr EOF;

// 重构表达式规则,明确优先级(从高到低),避免解析器乱组合
expr : Not expr                          # NotExpr
     | expr (Mul|Div) expr               # MulDivExpr
     | expr (Add|Sub) expr               # AddSubExpr
     | expr BooleanOperator expr         # CompareExpr
     | expr And expr                     # AndExpr
     | expr Or expr                      # OrExpr
     | atom                              # AtomExpr;

// 定义所有最小的原子表达式单元,明确边界
atom : boolean 
     | invoker 
     | entity 
     | number 
     | String 
     | '(' expr ')'; // 补充括号支持,符合常规表达式逻辑

entity : ObjectSymbol Identifier;
boolean : 'true'|'false';
invoker : entity attribute+;
attribute : Dot Identifier;
number : Integer | Float ;

// 词法规则
Identifier : Letter (Letter|JavaIDDigit)* ;
Integer : '-'? INT ;
Float : '-'? INT Dot [0-9]+; // 确保浮点数至少有一个小数位(可按需改回[0-9]*)
Mul : '*';
Div : '/';
Add : '+';
Sub : '-';
BooleanOperator : '>'|'>='|'<'|'<='|'=='|'!=';
And : '&&';
Or : '||';
Not:'!';
Dot : '.';
ObjectSymbol : '#';
String : '"' (~["\\] | '\\' .)* '"'; // 补全字符串匹配规则

// 辅助片段定义
fragment INT : '0' | [1-9][0-9]*;
fragment Letter : [a-zA-Z_];
fragment JavaIDDigit : [0-9a-zA-Z_];

WS : [ \t\n\r]+ -> skip ;

关键修改点解析

  1. 给statement加上EOF
    这是最关键的一步!原规则statement : expr;只要求解析器找到一个合法表达式就结束,不管后面有没有垃圾字符。加上EOF后,解析器必须匹配整个输入的所有字符,比如3ww会被检测到3之后的ww无法匹配任何合法规则,直接报错。

  2. 重构expr规则,明确原子边界
    把所有最小单元(数字、布尔值、实体等)放到atom规则里,让表达式结构更清晰,避免解析器把数字和后面的标识符错误组合成“合法”表达式。同时调整了优先级,让语法逻辑符合常规运算顺序(逻辑非>乘除>加减>比较>逻辑与或)。

  3. 补全String词法规则
    原代码里String规则是空的,这里补充了标准的双引号字符串匹配逻辑,支持转义字符。

  4. 优化Float规则(可选)
    原规则允许像-.这种非法浮点数,修改为[0-9]+确保至少有一个小数位;如果需要支持.5这种格式,可以改成'-'? (INT Dot [0-9]* | Dot [0-9]+)。

测试效果

修改后:

  • 合法输入#user.age>3或#user.age>3 && #user.age<2能正常解析
  • 非法输入#user.age>3ww或#user.age>3ww && #user.age<2会直接触发语法错误,完全符合你的预期。

内容的提问来源于stack exchange,提问作者Lson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:29:09