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

时间:2019-03-25 13:25:12

标签: antlr antlr4

我一直在使用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

1 个答案:

答案 0 :(得分:1)

您的问题与赋值语句无关。加法根本不起作用-不管它们是否属于作业。因此,最简单的输入错误将是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将被解析为应用于整数{{1}的一元减号) },而不仅仅是整数2,但这不是问题。