如何在动作代码中处理有条件的现有组件?

时间:2014-01-06 09:09:24

标签: antlr4

这是我从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为听众提供了这个问题的解决方案,但我没有使用听众,我的要求是在动作代码中处理。

2 个答案:

答案 0 :(得分:3)

至少有两种可能的方法可以解决这个问题:

  1. “ANTLR 4”的方法是创建一个监听器或访问者,而不是将Java代码放在嵌入语法本身的动作中。这是我甚至考虑在我自己的语法中解决问题的唯一方法。

  2. 如果您仍然使用嵌入式操作,则检查项目是否存在的最有效方法是访问ctx属性,例如$unaryOp.ctx。此属性解析为UnaryOpContext您假设$unaryOp可以自行访问。

答案 1 :(得分:1)

ANTLR希望您访问一个属性。请改为使用text属性:$unaryOp.text==null