对于+, - ,/,*等的正确优先级评估,正确的语法应该是什么?

时间:2014-08-20 20:03:00

标签: antlr4

我的语法有这些规则

 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) 

根据规则有意义(在MINUS之前加上)。

但是,如果我在Excel中评估相同的表达式,或者例如将它分配给C#中的double,在两种情况下结果都是-27.3。这是因为他们将规则评估为

(((40+10)-(2*40)) + (100/40)) + 0.2

哪个是“正确的”? -32.7在技术上是正确的,因为这是规则所要求的。但是如何改变语法以匹配Excel / C#中的结果?

2 个答案:

答案 0 :(得分:5)

如果您将+-组合在一个替代方案中,它应该有效。我更改了my demo evaluator on GitHub中的语法,如下所示:

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
 ;

然后使用以下代码进行测试:

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

-27.3将打印在我的控制台上。

答案 1 :(得分:1)

要在这样的表达式上获得正确的操作顺序,您需要设置嵌套规则。将更高优先级运算符更深解析为更接近主表达式。举个例子,我指出了我为Jison编写的语法,这是一个类似的语法工具。可以看到代码here

你将一个expr表达式分解为几个较小的表达式,每个&#34;级别&#34;运算符优先级,例如:

expr
  : comp_expr
  | expr0
  ;

expr0
  : or_expr
  | expr1
  ;

expr1
  : and_expr
  | expr2
  ;

expr2
  : add_expr
  | expr3
  ;

expr3
  : mult_expr
  | expr4
  ;

expr4
  : exp_expr
  | primary
  ;