AnTLR4优先级奇怪的行为

pin*_*ker 5 grammar antlr antlr4

我有一个非常简单的测试语法如下:

grammar Test;

statement: expression EOF;

expression
    :   Identifier
        |   expression binary_op expression
        |   expression assignment_operator expression
        |   expression '.' Identifier 
    ;

binary_op: '+';
assignment_operator : '='  ;

Identifier : [a-zA-Z]+ ;
WS : [ \n\r\t]+ -> channel(HIDDEN) ;
Run Code Online (Sandbox Code Playgroud)

使用此版本的语法,如果我编写以下代码,我会得到预期的行为:

b.x + b.y 
Run Code Online (Sandbox Code Playgroud)

我得到了一棵树 (+ (. b x) (. b y))

但是,如果我替换expression binary_op expressionexpression '+' expression我得到一个非常不同的树:(. (+ (. b x) b) y)

这有什么解释吗?

谢谢

GRo*_*erg 0

解析器中的文字可能会造成混乱。检查并修复生成解析器时报告的错误/警告。可能需要将文字从解析器规则移动到词法分析器规则。

您可以通过转储令牌流来验证词法分析器是否按预期运行。这将为理解解析器所采取的路径提供清晰的基础。

更新

您列出的解析树表示形式都不适合 Antlr4 解析树。尽管如此,尝试了你的语法的两种变体,我始终得到:

令牌转储:

Identifier: [@0,0:0='b',<4>,1:0]
Dot: [@1,1:1='.',<3>,1:1]
Identifier: [@2,2:2='x',<4>,1:2]
null: [@4,4:4='+',<1>,1:4]
Identifier: [@6,6:6='b',<4>,1:6]
Dot: [@7,7:7='.',<3>,1:7]
Identifier: [@8,8:8='y',<4>,1:8]
Run Code Online (Sandbox Code Playgroud)

树转储:

(statement (expression (expression (expression (expression b) . x) + (expression b)) . y) <EOF>)
Run Code Online (Sandbox Code Playgroud)

使用

ParseTree tree = parser.statement();
System.out.print(tree.toStringTree(parser));
Run Code Online (Sandbox Code Playgroud)

此特定令牌转储中的snull是因为符号首先在解析器中定义。