我是ANTLR的新手,我正在尝试使用ANTLR4和C#为计算器应用程序生成一个相对简单的解析器。这是我的语法文件。
parser grammar CalculatorExpressionParser;
options{
language = CSharp2;
}
expr: FUNC expr? (COMMA expr)* RIGHTPAREN #CallFunction
| LEFTPAREN expr RIGHTPAREN #Parens
| expr POW<assoc=right> expr #Pow
| expr op=(MULTIPLY | DIVIDE)? expr #MultDivide
| expr op=(ADD | SUBTRACT) expr #AddSubtract
| SUBTRACT expr #Negative
| NUMBER #Number
;
我编写了一个自定义词法分析器来生成标记,以便在解析之前支持隐式乘法和变量转换为它们的数字等价。
但在输入后我得到以下结果。
2+6/3 => 4 (correct)
6/3+2 => 1.2 (should be 4)
6/(3+2) => 4 (also correct)
1+2*3 => 7 (correct)
2*3+1 => 8 (should be 7 too)
(2*3)+1 => 7 (correct)
请注意,我尝试关闭错误恢复功能并将其设置为报告所有歧义错误,而且我似乎没有得到任何错误。
无论如何,如果我通过删除?将语法更改为以下内容?在除法/乘法运算符之后,它似乎工作得很好,除了不再支持隐式乘法。
parser grammar CalculatorExpressionParser;
options{
language = CSharp2;
}
expr: FUNC expr? (COMMA expr)* RIGHTPAREN #CallFunction
| LEFTPAREN expr RIGHTPAREN #Parens
| expr POW<assoc=right> expr #Pow
| expr op=(MULTIPLY | DIVIDE) expr #MultDivide
| expr op=(ADD | SUBTRACT) expr #AddSubtract
| SUBTRACT expr #Negative
| NUMBER #Number
;
我想知道为什么要放?打破匹配顺序?有没有一种简单的方法来解决这个问题?
答案 0 :(得分:1)
将expr语句拆分为多个语句,以便获得正确的操作顺序。
通常情况如下:
注意每个expr如何只处理一组数学运算,然后调用低优先级规则。通常,最低规则是您的原子运算符,如INT
或FLOAT
所以在这种情况下你处理逻辑AND和OR然后比较,然后是指数,然后是乘法/除法然后加法/减法。
注意我还应该指出,在这里我创建了一个AST树而不是内联操作。
expr
: subExpr -> ^(EXPR subExpr)
;
subExpr : logicalAndExp (addSubtractOp^ logicalAndExp)*
;
logicalAndExp
: logicalOrExp (multiplyDivideOp^ logicalOrExp)*
;
logicalOrExp
: comparatorExp (CARET^ comparatorExp)*
;
comparatorExp
: powExp (comparatorOp^ powExp)*
;
powExp : multExp (BARBAR^ multExp)*
;
multExp
: expressionAtom (AMPAMP^ expressionAtom)*
;expression
: subExpr -> ^(EXPR subExpr)
;
subExpr : logicalAndExp (addSubtractOp^ logicalAndExp)*
;
logicalAndExp
: logicalOrExp (multiplyDivideOp^ logicalOrExp)*
;
logicalOrExp
: comparatorExp (CARET^ comparatorExp)*
;
comparatorExp
: powExp (comparatorOp^ powExp)*
;
powExp : multExp (BARBAR^ multExp)*
;
multExp
: expressionAtom (AMPAMP^ expressionAtom)*
;
答案 1 :(得分:1)
“expr expr”不符合运算符的模式,尽管ANTLR 4.2可能会处理此问题。 Sam仍在努力更新C#目标。