Antlr4 对于+;,-,/,*,的正确优先级计算,正确的语法应该是什么,等
我的语法有这些规则Antlr4 对于+;,-,/,*,的正确优先级计算,正确的语法应该是什么,等,antlr4,Antlr4,我的语法有这些规则 expression : expression EQ conditionalOrExpression #eqExpr | expression NEQ conditionalOrExpression #neqExpr | expression LT conditionalOrExpression #ltExpr | expression GT condit
expression
: expression EQ conditionalOrExpression #eqExpr
| expression NEQ conditionalOrExpression #neqExpr
| expression LT conditionalOrExpression #ltExpr
| expression GT conditionalOrExpression #gtExpr
| expression LTEQ conditionalOrExpression #lteqExpr
| expression GTEQ conditionalOrExpression #gteqExpr
| conditionalOrExpression #next
;
conditionalOrExpression
: conditionalOrExpression OR conditionalAndExpression #orExpr
| conditionalAndExpression #and
;
conditionalAndExpression
: conditionalAndExpression AND additiveExpression #andExpr
| additiveExpression #add
;
additiveExpression
: additiveExpression PLUS multiplicativeExpression #plusExpr
| additiveExpression MINUS multiplicativeExpression #minusExpr
| multiplicativeExpression #multiplicative
;
multiplicativeExpression
: multiplicativeExpression MULT unaryExpression #multExpr
| multiplicativeExpression DIV unaryExpression #divExpr
| unaryExpression #unary
;
unaryExpression
: MINUS unaryExpression #unaryMinusExpr
| NOT unaryExpression #notExpr
| atom #atomExpr
;
function
: ID OPAR (parameter (',' parameter)*)? CPAR
;
parameter
: STRING #stringParameter
| expression #exprParameter
;
atom
: OPAR expression CPAR #parExpr
| (INT | FLOAT) #numberAtom
| (TRUE | FALSE) #booleanAtom
| ID #idAtom
| function #functionAtom
;
我已经实现了适当的访问者
如果我计算“40+10-(2*40)+(100/40)+0.2”,结果是-32.7。这是因为表达式的计算结果为
(40+10) - (((2*40) + (100/40)) + 0.2)
根据规则(加号在减号之前)这是有意义的
但是,如果我在Excel中计算相同的表达式,或者例如在C#中将其分配给一个double,那么在这两种情况下,结果都是-27.3。这是因为他们将规则评估为
(((40+10)-(2*40)) + (100/40)) + 0.2
那么哪一个是“正确的”-32.7在技术上是正确的,因为这是规则规定的。但是语法应该如何更改以匹配Excel/C#?中的结果要在这样的表达式上获得正确的操作顺序,您需要设置嵌套规则。在中更靠近主表达式的位置解析优先级更高的运算符。举个例子,我会告诉你我为Jison编写的语法,一个类似的语法工具。代码可以看到 对于运算符优先级的每个“级别”,将一个
expr
表达式拆分为几个较小的表达式,例如:
expr
: comp_expr
| expr0
;
expr0
: or_expr
| expr1
;
expr1
: and_expr
| expr2
;
expr2
: add_expr
| expr3
;
expr3
: mult_expr
| expr4
;
expr4
: exp_expr
| primary
;
如果将
+
和-
组合在一个备选方案中,则应该可以使用。我在中更改了语法如下:
expr
: expr POW<assoc=right> expr #powExpr
| MINUS expr #unaryMinusExpr
| NOT expr #notExpr
| expr op=(MULT | DIV | MOD) expr #multiplicationExpr
| expr op=(PLUS | MINUS) expr #additiveExpr
| expr op=(LTEQ | GTEQ | LT | GT) expr #relationalExpr
| expr op=(EQ | NEQ) expr #equalityExpr
| expr AND expr #andExpr
| expr OR expr #orExpr
| atom #atomExpr
;
值
-27.3
被打印在我的控制台上。C++(可能还有C#)看起来很模糊:[来源:这导致了一个复杂的解析树C#/Excel的方法是“正确的”,因为它是数学方法。你的语法,如你所说,把“加号”放在减号之前。在标准现代数学中使用的运算顺序中并非如此。它如下所示:括号内的表达式->指数->乘/除(以先到者为准,从左到右)->加/减(以先到者为准,从左到右)。当然,您可以自由地用自己的语言定义数学,但我强烈建议您使用标准形式,因为程序员已经熟悉它。现在如何将此代码左因子?(将所有的“| expr”组合成一条规则):)
MuLexer lexer = new MuLexer(new ANTLRInputStream("log(40 + 10 - (2*40) + (100/40) + 0.2);"));
MuParser parser = new MuParser(new CommonTokenStream(lexer));
new EvalVisitor().visit(parser.parse());