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");