我是 ANTLR 的新手,我正在尝试扩展此处介绍的简单计算器的示例。具体来说,我尝试添加一些简单的函数,负数等,以熟悉 ANTLR。但是,我在尝试实现“隐式”乘法时遇到了一些问题(例如,3cos(2)sin(2) 将被解释为 3*cos(2)*sin(2))。
我在 Stack Overflow 上发现了一个具有相同问题的问题(此处)。该问题的解决方案的一般形式看起来像我自己找到的,所以我不确定我的问题出在哪里。
我的语法如下。如果没有这| p2 = signExpr {$value *= $p2.value;}
条线(最后一行multiplicationExpr
),根据我的测试,一切似乎都正常。当我添加这一行并运行它时antlr
,我收到以下错误:
error(211): calculator.g:24:3: [fatal] rule multiplicationExpr has non-LL(*) decision due to recursive rule invocations reachable from alts 3,4. Resolve by left-factoring or using syntactic predicates or using backtrack=true option.
warning(200): calculator.g:24:3: Decision can match input such as "'-' FLOAT" using multiple alternatives: 3, 4
As a result, alternative(s) 4 were disabled for that input
启用backtrack
会导致我的一些(正常工作的)测试表达式的计算错误。此外,警告谈到了替代方案 3 和 4 multiplicationExpr
,但我在该块中只有三个替代方案,这让我感到困惑。
有人能指出我语法中的错误吗,如下所示?
grammar calculator;
eval returns [double value]
: exp = additionExpr {$value = $exp.value;}
;
additionExpr returns [double value]
: m1 = multiplicationExpr {$value = $m1.value;}
( '+' m2 = multiplicationExpr {$value += $m2.value;}
| '-' m2 = multiplicationExpr {$value -= $m2.value;}
)*
;
multiplicationExpr returns [double value]
: p1 = signExpr {$value = $p1.value;}
( '*' p2 = signExpr {$value *= $p2.value;}
| '/' p2 = signExpr {$value /= $p2.value;}
| p2 = signExpr {$value *= $p2.value;}
)*
;
signExpr returns [double value]
: ( '-' a = funcExpr {$value = -1*$a.value;}
) | ( a = funcExpr {$value = $a.value;}
)
;
funcExpr returns [double value]
: ( 'cos' s = signExpr {$value = Math.cos($s.value);}
) | ( 'sin' s = signExpr {$value = Math.sin($s.value);}
) | ( s = powExpr {$value = s;}
)
;
powExpr returns [double value]
: s1 = atomExpr {$value = $s1.value;}
( '^' s2 = signExpr {$value = Math.pow($value, $s2.value);}
)?
;
atomExpr returns [double value]
: f = FLOAT {$value = Double.parseDouble($f.text);}
| '(' exp = additionExpr ')' {$value = $exp.value;}
;
FLOAT
: ('0'..'9')+ ('.' ('0'..'9')*)? EXPONENT?
| '.' ('0'..'9')+ EXPONENT?
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;