这是我从antlr3迁移到antlr4时面临的另一个问题。此问题与用于处理规则的条件组件的 java 操作代码有关。下面显示了一个示例。
以下语法+代码在antlr3中工作。在这里,如果一元运算符不存在,则返回值"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] - 这里 $s 2 在 antlr4 中为空:
ifStmt returns [Stmt s]
: 'if' '(' e=cond ')' s1=stmt ('else' s2=stmt)?
{$s = new StmtIf($e.e, $s1.s, $s2.s);}
;
注意:问题16392152为这个问题提供了与侦听器的解决方案,但我没有使用侦听器,我的要求是在操作代码中处理这个问题。
潜在的方法可以纠正此问题:
"ANTLR 4"的方法是创建一个侦听器或访问者,而不是将Java代码放在嵌入在语法本身的操作中。这是我甚至考虑在自己的语法中解决问题的唯一方法。
如果您仍然使用嵌入式操作,则检查该项是否存在的最有效方法是访问
ctx
属性,例如$unaryOp.ctx
.此属性解析为您假定可由$unaryOp
本身访问的UnaryOpContext
。
ANTLR 希望您访问属性。试试它的text
属性:$unaryOp.text==null