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

ANTLR4中point规则为何匹配多个数字?

问题分析与解决方案

你遇到的核心问题是ANTLR4词法规则的匹配优先级导致的token拆分错误,让我们一步步拆解:

问题根源

ANTLR的词法分析遵循两个关键规则:

  1. 最长匹配优先:会尽可能匹配最长的符合规则的字符串。
  2. 规则定义顺序优先:如果多个规则都能匹配当前输入片段,会选择先定义的规则。

看你的原语法:

INT: [0-9]+;
FLOAT: [0-9]*'.'?[0-9]+ ;
NUMBER: (INT | FLOAT) ;

当输入2.0时,词法分析器首先会匹配2到INT规则(因为INT定义在FLOAT前面),剩下的.0才会被匹配为FLOAT。这样7 2.0会被拆成三个token:7(INT)、2(INT)、.0(FLOAT)。

而你的point: num num;规则需要两个num(即两个NUMBER),解析器会把前两个token(7和2)作为point的两个num,剩下的.0就没有对应的规则可以匹配,于是出现了mismatched input '0' expecting NUMBER的错误。

修复方案

我们可以通过合并整数与浮点数的词法规则来彻底避免顺序问题,同时优化语法的严谨性:

修改后的完整语法:

grammar example;

// 隐藏空白字符
WS: [ \t\r\n]+ -> channel(HIDDEN);

// 合并整数和浮点数为一个NUMBER规则,覆盖所有数字情况
NUMBER: 
    [0-9]+ ('.' [0-9]+)?  // 匹配整数(如7)和带整数部分的浮点数(如2.0)
    | '.' [0-9]+;          // 匹配不带整数部分的浮点数(如.5)

// 标识符规则保持不变
IDSTRING: [a-zA-Z_] [a-zA-Z0-9_]*;

// 解析规则
id: IDSTRING;
num: NUMBER;
sem: ';' ;
point: num num;
// 修正END的写法:原语法的'END '带空格,WS已被隐藏,直接写'END'即可
macro: 'MACRO' id macroprops* 'END' id;
macroprops: macroorigin ;
macroorigin: 'ORIGIN' point sem;

关键修改点说明

  1. 合并NUMBER规则:把INT和FLOAT合并成一个规则,确保任何数字形式都会被识别为单个NUMBERtoken,彻底解决顺序优先级问题。
  2. 修正macro规则中的END:原语法里的'END '包含空格,但WS已经被放到隐藏通道,解析器不会处理显式空格,改为'END'后,会自动跳过END和id之间的空白字符,更符合预期。

测试验证

重新运行你的命令:

antlr4 example.g4 -o example/
cd example
javac *.java
echo -e "MACRO m_1\n ORIGIN 7 2.0 ;\nEND m_1" | grun example macro -tree

此时应该会输出正确的解析树:

(macro MACRO (id m_1) (macroprops (macroorigin ORIGIN (point (num 7) (num 2.0)) (sem ;))) END (id m_1))

内容的提问来源于stack exchange,提问作者Paul Würtz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:54:18