【发布时间】:2022-11-09 22:41:01
【问题描述】:
语法定义
据我了解,ANTLR4 支持左递归以尊重算术的优先顺序。话虽如此,语法如下:
grammar Arithmetic;
arithmetic: arithmeticExpression;
arithmeticExpression:
LPARAN inner = arithmeticExpression RPARAN # Parentheses
| left = arithmeticExpression POW right = arithmeticExpression # Power
| left = arithmeticExpression MUL right = arithmeticExpression # Multiplication
| left = arithmeticExpression DIV right = arithmeticExpression # Division
| left = arithmeticExpression ADD right = arithmeticExpression # Addition
| left = arithmeticExpression SUB right = arithmeticExpression # Subtraction
| arithmeticExpressionInput # ArithmeticInput;
arithmeticExpressionInput: NUMBER;
number: NUMBER;
/* Operators */
LPARAN: '(';
RPARAN: ')';
POW: '^';
MUL: '*';
DIV: '/';
ADD: '+';
SUB: '-';
/* Data Types */
NUMBER: '-'? [0-9]+;
/* Whitespace & End of Lines */
EOL: '\r'? '\n';
WS: [ \t]+ -> channel(HIDDEN);
注意:我已经简化了测试的语法。
输入
5 + 21 / 7 * 3输出解析树
问题
在从
arithmetic开始的输出解析树中。您可以看到优先顺序没有遵循 PEMDAS,即使它是通过语法中的左递归定义的。在使用函数调用为VisitAddition调试 Antlr 生成的访问者代码时也会观察到这一点。我用谷歌搜索了这个,与示例相比,我看不出我做错了什么,因为它们看起来都一样。
环境
ANTLR 版本:4.11.1
构建目标:CSharp
.NET 项目包:
- Antlr4BuildTasks@11.1.0
- Antlr4.Runtime.Standard@4.11.1
【问题讨论】:
-
你能解释一下结果与你想要的有什么不同吗?乘法的优先级高于除法的事实?这就是您在语法中定义它的方式。如果您希望乘法和除法具有相同的优先级,则需要在相同的选项中将它们一起定义(加号和减号相同)。
-
@sepp2k,当然,我想遵循 PEMDAS 的数学优先顺序。但是,它目前没有遵循该命令。就像解析语法时,它在乘法之前调用加法是错误的。这导致计算时结果在数学上不正确。
-
您展示的解析树等同于
5 + (21 / (7 * 3))。数学上正确的是5 + ((21 / 7) * 3)。所以+(相对于*和/)的优先级很好。 -
数学中通常的约定是
+与-具有相同的优先级,*与/具有相同的优先级。 “PEMDAS”应该读作“PE(MD)(AS)”(或者根本不使用首字母缩写词)。如果您将其解释为严格的顺序,则您编写的语法是“PEMDAS”的正确实现。那只是不正确的解释。 -
明白了,我的错。我想在我的脑海中,我期待看到
VisitX按优先顺序(PEMDAS)导致我认为它以错误的顺序解析!我将测试更多的方程并确保我得到正确的输出。