这是我从antlr3迁移到antlr4时遇到的另一个问题。此问题与用于处理规则的条件组件的java操作代码有关。一个例子如下所示。
以下语法+代码在antlr3中有效。这里,如果一元运算符不存在,则值为' 0' 0返回,java代码检查此值并采取适当的操作。
exprUnary returns [Expr e]
: (unaryOp)? e1=exprAtom
{if($unaryOp.i==0) $e = $e1.e;
else $e = new ExprUnary($unaryOp.i, $e1.e);
}
;
unaryOp returns [int i]
: '-' {$i = 1;}
| '~' {$i = 2;}
;
在antlr4中,此代码在运行期间导致空指针异常,因为' unaryOp'是' null'如果它不存在。但是,如果我更改下面的代码,那么antlr生成本身会报告错误:
if($unaryOp==null) ...
java org.antlr.v4.Tool try.g4
error(67): missing attribute access on rule reference 'unaryOp' in '$unaryOp'
如何为antlr4编写动作?
这种情况的另一个例子是if-then- [else] - 这里$ s2在antlr4中为null:
ifStmt returns [Stmt s]
: 'if' '(' e=cond ')' s1=stmt ('else' s2=stmt)?
{$s = new StmtIf($e.e, $s1.s, $s2.s);}
;
注意:问题16392152为听众提供了这个问题的解决方案,但我没有使用听众,我的要求是在动作代码中处理。
答案 0 :(得分:3)
至少有两种可能的方法可以解决这个问题:
“ANTLR 4”的方法是创建一个监听器或访问者,而不是将Java代码放在嵌入语法本身的动作中。这是我甚至考虑在我自己的语法中解决问题的唯一方法。
如果您仍然使用嵌入式操作,则检查项目是否存在的最有效方法是访问ctx
属性,例如$unaryOp.ctx
。此属性解析为UnaryOpContext
您假设$unaryOp
可以自行访问。
答案 1 :(得分:1)
ANTLR希望您访问一个属性。请改为使用text
属性:$unaryOp.text==null