Antlr4 解析器未正确解析重新分配语句

Antlr4 parser not parsing reassignment statement correctly

我一直在使用 Antlr4 创建语法分析器,并希望添加变量重新分配(无需声明新变量)

我试过将重新赋值语句更改为表达式,但这并没有改变任何东西

这是我的语法的简化版本:

grammar MyLanguage;

program: statement* EOF;

statement
    : expression EOC
    | variable EOC 
    | IDENTIFIER ASSIGNMENT expression EOC
    ;

variable: type IDENTIFIER (ASSIGNMENT expression)?;

expression
    : STRING
    | INTEGER
    | IDENTIFIER
    | expression MATH expression
    | ('+' | '-') expression
    ;

MATH:       '+' | '-' | '*' | '/' | '%' | '//' | '**';
ASSIGNMENT: MATH? '=';
EOC:        ';';
WHITESPACE: [ \t\r\n]+ -> skip;

STRING:     '"' (~[\u0000-\u0008\u0010-\u001F"] | [\t])* '"' | '\'' (~[\u0000-\u0008\u0010-\u001F'] | [\t])* '\'';
INTEGER:    '0' | ('+' | '-')? [1-9][0-9]*;
IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*;

type:      'str';

如果还有其他相关问题,请询问

所以我尝试解析

str test = "empty";
test = "not empty";

这有效,但是当我尝试时(fibbionaci 函数的一部分)

temp = n1;
n1 = n1 + n2;
n2 = temp;

出现错误并将其解析为

temp = n1; //statement
n1 = n1 //statement - <missing ';'>
+n2; //statement
n2 = temp; //statement

您的问题与赋值语句无关。添加根本不起作用 - 无论它们是否是作业的一部分。因此,获得错误的最简单输入是 x+y;。如果您打印该输入的令牌流(例如使用 grun-tokens 选项),您将获得以下输出:

[@0,0:0='x',<IDENTIFIER>,1:0]
[@1,1:1='+',<'+'>,1:1]
[@2,2:2='y',<IDENTIFIER>,1:2]
[@3,3:3=';',<';'>,1:3]
[@4,4:3='<EOF>',<EOF>,1:4]
line 1:1 no viable alternative at input 'x+'

现在将其与 x*y; 进行比较,效果很好:

[@0,0:0='x',<IDENTIFIER>,1:0]
[@1,1:1='*',<MATH>,1:1]
[@2,2:2='y',<IDENTIFIER>,1:2]
[@3,3:3=';',<';'>,1:3]
[@4,4:3='<EOF>',<EOF>,1:4]

这里的重要区别是 * 被识别为 MATH 标记,但 + 不是。它被识别为 '+' 令牌。

发生这种情况是因为您在备选 | ('+' | '-') expression 中引入了单独的 '+'(和 '-')令牌类型。因此,每当词法分析器看到 + 时,它都会生成一个 '+' 标记,而不是 MATH 标记,因为解析器规则中的字符串文字优先于命名的词法分析器规则。

如果您将 MATH 改为解析器规则 math(或者 mathOperator),所有运算符都将是文字,问题就会消失。也就是说,您可能不希望所有数学运算符都使用单一规则,因为这不会为您提供您想要的优先级,但这是一个不同的问题。

PS:x+1 之类的东西仍然不起作用,因为它会将 +1 视为单个 INTEGER 标记。您可以通过从 INTEGER 规则中删除前导 +- 来解决这个问题(这样 x = -2 将被解析为应用于整数 2 而不仅仅是整数 -2,但这不是问题)。