Antlr4:无法理解为什么将某些东西分解成子规则不起作用

Antlr4: Can't understand why breaking something out into a subrule doesn't work

我还是 Antlr4 的新手,我遇到了一个可能非常愚蠢的问题。

这是我的 .g4 文件中的一个片段:

assignStatement
    : VariableName '=' expression ';'
    ;

expression
    :   (value | VariableName)
        | bin_op='(' expression ')'
        | expression UNARY_PRE_OR_POST
        | (UNARY_PRE_OR_POST | '+' | '-' | '!' | '~' | type_cast) expression
        | expression MUL_DIV_MOD expression
        | expression ADD_SUB expression
    ;

VariableName
    : ( [a-z] [A-Za-z0-9_]* )
    ;

// Pre or post increment/decrement
UNARY_PRE_OR_POST
    : '++' | '--'
    ;

// multiply, divide, modulus
MUL_DIV_MOD
    : '*' | '/' | '%'
    ;

// Add, subtract
ADD_SUB
    : '+' | '-'
    ;

我的示例输入:

myInt = 10 + 5;
myInt = 10 - 5;
myInt = 1 + 2 + 3;
myInt = 1 + (2 + 3);
myInt = 1 + 2 * 3;
myInt = ++yourInt;
yourInt = (10 - 5)--;

第一个示例行 myInt = 10 + 5; 行产生此错误:

line 22:11 mismatched input '+' expecting ';'
line 22:14 extraneous input ';' expecting {<EOF>, 'class', '{', 'interface', 'import', 'print', '[', '_', ClassName, VariableName, LITERAL, STRING, NUMBER, NUMERIC_LITERAL, SYMBOL}

我在每一行中都遇到了类似的问题。

如果我做一个更改,一大堆错误就会消失:

        | expression ADD_SUB expression

改成这样:

        | expression ('+' | '-') expression

我已经尝试了很多东西。我试过同时使用词法分析器和解析器规则(即,将其称为 add_subADD_SUB)。我尝试了各种括号组合。

我试过了:

ADD_SUB: [+-];

令人恼火的是,只要我没有因 +-* 产生的错误,前增量行和 post 增量行就不会产生任何错误。然而他们依赖 UNARY_PRE_OR_POST。当然,也许它并没有真正使用它,而是使用了我不清楚的其他东西。

目前,我只是删除了子规则语法,并将所有内容嵌入到主规则中。但我想了解发生了什么。

所以...正确的方法是什么:

不要在解析器规则中使用文字标记(除非您知道自己在做什么)。

对于语法:

expression
    :   '+' expression
    |   ...
    ;

ADD_SUB
    : '+' | '-'
    ;

ANTLR 将为文字 '+' 创建词法分析器规则,使语法看起来像这样:

expression
    :   T__0 expression
    |   ...
    ;

T__0 : '+';

ADD_SUB
    : '+' | '-'
    ;

导致输入 + 永远不会成为 ADD_SUB 标记,因为 T__0 总是首先匹配它。这就是词法分析器的简单操作方式:尝试为每个词法分析器规则匹配尽可能多的字符,并且当 2 个(或更多)匹配相同数量的字符时,让第一个定义的“赢”。

改为执行以下操作:

expression
    : value
    | '(' expression ')'
    | expression UNARY_PRE_OR_POST
    | (UNARY_PRE_OR_POST | ADD | SUB | EXCL | TILDE | type_cast) expression
    | expression (MUL | DIV | MOD) expression
    | expression (ADD | SUB) expression
    ;

value
    : ...
    | VariableName
    ;

VariableName
    : [a-z] [A-Za-z0-9_]*
    ;

UNARY_PRE_OR_POST
    : '++' | '--'
    ;

MUL : '*';
DIV : '/';
MOD : '%';
ADD : '+';
SUB : '-';
EXCL : '!';
TILDE : '~';