我一直在使用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
答案 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
,但这不是问题。