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());