使用ANTLR 4.7.1考虑以下简单语法。
grammar Grammar;
ID: [a-z];
DOT: '.';
LPAREN: '(';
RPAREN: ')';
SEMICOLON: ';';
LT: '<';
GT: '>';
term
: ID LT ID GT LPAREN expr RPAREN # CallExpr
| ID # Id
| LPAREN expr RPAREN # ParenExpr
;
expr
: term DOT? # PrimaryExpr
| expr bop=(GT | LT) expr # BinaryExpr
;
update : expr SEMICOLON ;
当将代码段a<b>(c)
与规则expr
匹配时,ANTLR报告存在歧义,因为表达式可以是PrimaryExpr
或BinaryExpr
其操作数之一也是BinaryExpr
。这是预料之中的,这是我们开发的语言的功能。由于优先级高,解析器更喜欢前者,这正是我们想要的。
当a<b>(c);
与update
匹配时,所有内容也都按预期方式工作-含糊不清,但是PrimaryExpr
具有优先权。
但是,当我尝试将a<b>(c)
与update
进行匹配时,我希望除了报告丢失的分号外,还有相同的歧义。相反,仅匹配BinaryExpr
规则。这是一个问题,因为这样的代码段可能会出现在正在编写的代码中,并且会导致编辑器插件的自动完成功能(和其他功能)无法正常工作。有什么指示为什么会发生以及如何解决呢?
我尝试过的东西只会进一步增加混乱:
BinaryExpr
规则后,a<b>(c)
会匹配update
到PrimaryExpr
(缺少分号)。当我删除使用的ANTLR却不报告歧义时,如何将ANTLR转换为其他派生?DOT?
中删除PrimaryExpr
后,问题就消失了。update : expr (SEMICOLON | {notifyErrorListeners("Missing ';'");})
一起使用时,此问题已解决。我们可以使用第三个选项来解决此问题,它似乎并没有破坏我们的测试套件中的任何内容,但是我强烈感到自己并没有解决根本原因,而缺少了一些稍后会困扰我们的基本问题。
我发现了类似https://github.com/antlr/antlr4/issues/1545的问题,但是这个问题已经解决。