我有一个简单的语法,我必须为算术表达式实现评估器,并注意到特定的ANTLR。
语法:
start ::= expr
expr ::= term exprp
exprp ::= + term exprp
| - term exprp
| e
term ::= fact termp
termp ::= * fact termp
| / fact termp
| e
fact ::= ( expr ) | ID | NUM
带有属性的语法:
start ::= expr
expr ::= term {exprp.i = term.val} exprp {expr.val = exprp.val}
exprp ::= + term {exprp1.i = exprp.i + term.val} exprp1 {exprp.val = exprp1.val}
| - term {exprp1.i = exprp.i - term.val} exprp1 {exprp.val = exprp1.val}
| e {exprp.val = exprp.i}
term ::= fact {termp.i = fact.val} termp {term.val = termp.val}
termp ::= * fact {termp1.i = termp.i * fact.val} termp1 {termp.val = termp1.val}
| / fact {termp1.i = termp.i/fact.val} termp1 {termp.val = termp1.val}
| e {termp.val = termp.i}
fact ::= ( expr ) {fact.val = expr.val}
| NUM {fact.val = Integer.parseInt(NUM.text)}
我写了这个:
grammar Expr;
start
: expr EOF { System.out.println($expr.val); }
;
expr returns [int val]
: term exprP[$exprP.i = $term.val] { $val = $exprP.val; }
;
exprP[int i] returns [int val]
: { $val = $i; }
| '+' term e = exprP[$i + $term.val] { $val = $e.val; }
| '-' term e = exprP[$i - $term.val] { $val = $e.val; }
;
term returns [int val]
: fact termP[$termP.i = $fact.val] { $val = $termpP.val; }
;
termP[int i] returns [int val]
: { $val = $i; }
| '*' fact e = termP[$i * $fact.val] { $val = $e.val; }
| '/' fact e = termP[$i / $fact.val] { $val = $e.val; }
;
fact returns [int val]
: '(' expr ')' { $val = $expr.val; }
| NUM { $val = Integer.parseInt($NUM.text); }
;
ID : ('a'.. 'z'|'A'.. 'Z') ('a'.. 'z'|'A'.. 'Z'|'0'.. '9'|'_')* ;
NUM : '0'.. '9'+ ;
WS : (' ' | '\t' | '\r' | '\n')+ { skip (); } ;
但是当我用命令:
调用ANTLR工具时java -cp antlr-3.5-complete.jar org.antlr.Tool Expr.g
存在以下错误:
error(115): II.2/Expr.g:0:: cannot access rule exprP's parameter: i
error(115): II.2/Expr.g:0:: cannot access rule termP's parameter: i
我明白错误在哪里,但我不知道如何解决它们。有人向我解释了什么是错的,我该如何解决?非常感谢你
答案 0 :(得分:3)
问题出在您的expr
和term
规则中。
在expr
中,您尝试分配$exprP.i
而不是仅传递参数。它应该如下所示。
expr returns [int val]
: term exprP[$term.val] { $val = $exprP.val; }
;
在expr
中,您尝试分配$termP.i
而不是仅传递参数。它应该如下所示。
term returns [int val]
: fact termP[$fact.val] { $val = $termpP.val; }
;
我认为较新版本的ANTLR 3(3.5.2是最新版本)在为这些错误提供行号和列号方面做得更好,但这可能是ANTLR 4的新功能。