我的语法有这些规则
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#中的结果?
答案 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
;