ANTLR:没有可行的替代错误

Yar*_*nov 6 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 at input 'foo'
(rule foo : bar ;)
Run Code Online (Sandbox Code Playgroud)

我的语法看起来像

grammar parsGen;

gram : rule SEMICOLON (NEWLINE+ rule SEMICOLON)* ;

rule : lRule | pRule ;

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

modificator : PLUS | ASTERISK | QUESTION ;

ID : LRULEID | PRULEID ;

LRULEID : UPPERLETTER (UPPERLETTER | LOWERLETTER | DIGIT)* ;
PRULEID : LOWERLETTER (UPPERLETTER | LOWERLETTER | DIGIT)* ;

STRING : ('\''.*?'\'') ;
SET : '\''.*?'\'..\''.*?'\'' ;

UPPERLETTER : [A-Z] ;
LOWERLETTER : [a-z] ;
DIGIT : [0-9] ;

NEWLINE : '\r\n'|'\n'|'\r' ;

PLUS : '+' ;
ASTERISK : '*' ;
QUESTION : '?' ;

LBRACE : '(' ;
RBRACE : ')' ;

SPACE : ' ' ;

COLON : ':' ;

PIPE : '|' ;

SEMICOLON : ';' ;
Run Code Online (Sandbox Code Playgroud)

那么我哪里可以犯错?我试图搜索到处(谷歌,SO等)错误"没有可行的选择",但它并没有真正帮助我.

Sam*_*ell 17

ANTLR词法分析器在使用解析器之前完全分配明确的令牌类型.当多个令牌类型可以匹配令牌时,出现在语法中的第一个令牌就是使用的令牌.对于您的语法,令牌不能同时具有类型ID和类型LRULEID.由于输入foo匹配这两个词法分析规则,第一个出现在语法使用,因此您的令牌是:ID,COLON,ID,SEMICOLON,<EOF>.

由于ID在解析器中从未实际引用令牌,因此我建议进行以下更改之一.这些选项中的任何一个都可以解决您所描述的问题,因此选择完全取决于最终语法的外观.

前言

您需要将空间引用更改SPACE+SPACE*,或者规则将在和之间至少需要一个空格字符.bar;

选项1

ID完全删除词法分析器规则.

选项2

  1. 更改ID为解析器规则,因此它不会尝试将令牌类型分配ID给所有标识符.

    id : LRULEID | PRULEID;
    
    Run Code Online (Sandbox Code Playgroud)
  2. pRule1通过引用更新规则id.

    pRule1 : ((id | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE+)+ ;
    
    Run Code Online (Sandbox Code Playgroud)

不相关的旁注

如果去掉最外层您的语法可能会更容易阅读+里面的封闭lRulepRule1规则,而是将它们添加到规则引用自己,是这样的.请注意,我SPACE按照前言中的描述更改了引用.

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* ;
Run Code Online (Sandbox Code Playgroud)