Antlr4词法层面如何支持整数与小数?解析自定义语法报错原因
关于Antlr4语法解析整数与小数的问题解答
问题描述
编写了一套支持整数和小数常规数学运算的Antlr4语法,定义如下:
grammar Calculation; calculation: expr EOF; // Parser rules expr: expr (ADD|SUB) expr | expr (MUL|DIV) expr | expr POWER expr | expr MODULAR expr | LEFT_BRACKET expr RIGHT_BRACKET | SQRT LEFT_BRACKET expr RIGHT_BRACKET | NUMBER ; // Lexer rules ADD: '+'; SUB: '-'; MUL: '*'; DIV: '/'; LEFT_BRACKET: '('; RIGHT_BRACKET: ')'; INT : [0-9]+; NUMBER: INT ('.' [0-9]+)?; POWER: '^'; SQRT: 'sqrt'; MODULAR: '%'; WS : [ \t\r\n]+ -> skip ;
但解析表达式(1+1)时,抛出警告:line 1:1 mismatched input'1 'expecting {'(), NUMBER,'sqrt'}。在expr规则中添加|INT后,解析恢复正常。疑问两点:
- 出现该错误的原因是什么?
- Antlr4如何在词法层面正确同时支持整数和小数?
问题解答
1. 错误原因解析
Antlr4的词法分析器遵循两个核心规则:
- 最长匹配原则:优先匹配长度最长的可能token
- 先定义先匹配原则:当多个规则能匹配相同长度的输入时,优先匹配先定义的规则
你的语法中先定义了INT : [0-9]+;,再定义NUMBER: INT ('.' [0-9]+)?;。输入1时,词法分析器会优先匹配INT类型的token,但expr规则只接受NUMBER类型,导致解析器找不到对应规则,抛出不匹配错误。添加|INT后,expr规则可以匹配INT类型的token,因此解析恢复正常。
2. 词法层面支持整数与小数的正确方式
不需要单独定义INT规则,因为整数本质是小数的特例(无小数点及后续数字)。直接将整数和小数的匹配逻辑合并到NUMBER规则中即可,修改后的词法规则如下:
// 移除原有的INT规则 NUMBER: [0-9]+ ('.' [0-9]+)?;
这样修改后:
- 输入整数(如
123)会被匹配为NUMBERtoken - 输入小数(如
123.45)也会被匹配为NUMBERtoken - 完全符合Antlr4的最长匹配原则,不会出现拆分匹配的问题
内容的提问来源于stack exchange,提问作者Apollo Elon
相关产品推荐
相关产品推荐

