Antlr:意外行为

Antlr:意外行为,antlr,Antlr,为什么这么简单的语法 grammar Test; expr : Int | expr '+' expr; Int : [0-9]+; 与输入不匹配1+1?它说“没有用于规则表达式的方法,或者它有参数”,但在我看来它应该是匹配的。看起来我已经有一段时间没有使用ANTLR了。。。ANTLRv3不支持左递归规则。它还支持您在文章中使用的类似正则表达式的字符类语法。我测试了这个版本,它在ANTLRWorks2(在ANTLR4上运行)中工作: 如果添加start规则,则ANTLR

为什么这么简单的语法

grammar Test;

expr
    :    Int | expr '+' expr;

Int
:    [0-9]+;

与输入不匹配
1+1
?它说“没有用于规则表达式的方法,或者它有参数”,但在我看来它应该是匹配的。

看起来我已经有一段时间没有使用ANTLR了。。。ANTLRv3不支持左递归规则。它还支持您在文章中使用的类似正则表达式的字符类语法。我测试了这个版本,它在ANTLRWorks2(在ANTLR4上运行)中工作:

如果添加
start
规则,则ANTLR可以推断
EOF
位于该规则的末尾。对于更复杂的规则,如
expr
expr2
,它似乎无法推断
EOF
,因为它们是递归的


下面有很多评论,下面是(ANTLR4的合著者)Sam Harwell的回复(重点补充):


您仍然希望在开始规则中包含显式EOF。OP直接使用expr面临的问题是ANTLR 4在内部将其重写为expr[int\u p](它对所有左递归规则都这样做),并且包含的测试装备无法直接执行带有参数的规则。添加开始规则可以解决此问题,因为TestRig能够执行该规则。:)


我已经发布了一个关于
EOF
的后续问题:

如果您的命令如下所示:

grun MYGRAMMAR xxx -tokens
将引发此异常:

No method for rule xxx or it has arguments
然后,将使用您在上述命令中指定的规则引发此异常。这意味着规则可能不存在

System.err.println("No method for rule "+startRuleName+" or it has arguments");

因此,如果它不是语法中的第一条(开始)规则,那么这里的
startRuleName
应该打印
xxx
。将
xxx
作为语法中的第一条规则来防止出现这种情况。

但是为什么编译器没有标记为错误,为什么第509行
表达式
被定义为左递归,并且似乎不是problem@IvanPetkov-问题比我想象的要多。我已经在AntlWorks中编辑了我的答案并测试了语法。它现在可以工作了。@IvanPetkov-好的,再次测试,现在它实际解析
1+1
。缺少
EOF
导致它以前无法接受整个输入。您仍然希望在
start
规则中包含显式
EOF
。OP直接使用
expr
面临的问题是,ANTLR 4在内部将其重写为
expr[int\u p]
(它对所有左递归规则都这样做),并且包含的TestRig无法直接执行带参数的规则。添加
start
规则可以解决此问题,因为TestRig能够执行该规则。:)另外,
Int
Int
作为ANTLR(版本3和版本4)中的词法规则同样有效。支持
INT
格式的唯一原因是它在代码中生成常量,这些常量遵循Java常量约定(所有大写)。
System.err.println("No method for rule "+startRuleName+" or it has arguments");