ANTLR:没有可行的替代错误
我的任务是编写简单的解析器生成器,因此我编写了类似ANTLR的语法,并尝试解析类似“foo:bar;”的简单文件,但得到了以下输出:ANTLR:没有可行的替代错误,antlr,parser-generator,Antlr,Parser Generator,我的任务是编写简单的解析器生成器,因此我编写了类似ANTLR的语法,并尝试解析类似“foo:bar;”的简单文件,但得到了以下输出: [@0,0:2='foo',<1>,1:0] [@1,3:3=':',<16>,1:3] [@2,4:6='bar',<1>,1:4] [@3,7:7=';',<18>,1:7] [@4,8:7='<EOF>',<-1>,1:8] line 1:0 no viable alternative
[@0,0:2='foo',<1>,1:0]
[@1,3:3=':',<16>,1:3]
[@2,4:6='bar',<1>,1:4]
[@3,7:7=';',<18>,1:7]
[@4,8:7='<EOF>',<-1>,1:8]
line 1:0 no viable alternative at input 'foo'
(rule foo : bar ;)
那么我在哪里会犯错误呢?我尝试到处搜索(谷歌等)错误“没有可行的替代方案”,但这并没有真正帮助我。ANTLR词法分析器在使用解析器之前完全分配明确的令牌类型。当多个标记类型可以匹配一个标记时,语法中出现的第一个标记类型就是所使用的标记类型。对于语法,标记不能同时具有类型
ID
和类型LRULEID
。由于输入的foo
与这两个lexer规则都匹配,因此使用语法中第一个出现的标记:ID
,COLON
,ID
,分号
,
由于ID
标记从未在解析器中实际引用,因此我建议进行以下更改之一。这两个选项中的任何一个都可以解决您所描述的问题,因此最终语法的外观完全取决于您的偏好
前言
您需要将空格引用从space+
更改为space*
,否则规则将要求在条
和之间至少有一个空格字符代码>
选项1
完全删除ID
lexer规则
选项2
将ID
更改为解析器规则,这样它就不会试图将令牌类型ID
分配给所有标识符
id : LRULEID | PRULEID;
通过引用id
更新pRule1
规则
pRule1 : ((id | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE+)+ ;
不相关的旁注
如果删除lRule
和pRule1
规则中最外层的+
闭包,而是将它们添加到规则引用本身,则语法可能更容易阅读,如下所示。请注意,我更改了前言中所述的空格
参考
lRule : LRULEID COLON lRule1+ ;
lRule1 : ((LRULEID | STRING | SET) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE* ;
pRule : PRULEID COLON pRule1+ ;
pRule1 : ((LRULEID | PRULEID) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE* ;
也可从以下网址:
表示解析器无法根据剩余的输入决定采用两条或多条路径中的哪一条。它跟踪违规输入的起始标记,还知道错误[发生]时解析器在不同路径中的位置
在我的例子中,为了调试,我在解析之前调用了lexer.nextToken()。反过来,如果没有lexer.reset(),则在输入EOF错误时没有可行的替代方案
lRule : LRULEID COLON lRule1+ ;
lRule1 : ((LRULEID | STRING | SET) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE* ;
pRule : PRULEID COLON pRule1+ ;
pRule1 : ((LRULEID | PRULEID) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE* ;