title: how to handle conditionally existing components in action code?
body: <p>This is another problem I am facing while migrating from antlr3 to antlr4. This problem is with the java action code for handling conditional components of rules. One example is shown below.</p>
  
  <p>The following grammar+code worked in antlr3. Here, if the unary operator is not present, then a value of '0' is returned, and the java code checks for this value and takes appropriate action.</p>
  
  <pre><code>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;}
      ;
  </code></pre>
  
  <p>In antlr4, this code results in a null pointer exception during a run, because 'unaryOp' is 'null' if it is not present. But if I change the code like below, then antlr generation itself reports an error:</p>
  
  <pre><code>if($unaryOp==null) ...
  java org.antlr.v4.Tool try.g4
  error(67): missing attribute access on rule reference 'unaryOp' in '$unaryOp'
  </code></pre>
  
  <p>How should the action be coded for antlr4?</p>
  
  <p>Another example of this situation is in if-then-[else] - here $s2 is null in antlr4:</p>
  
  <pre><code>ifStmt returns [Stmt s]
      : 'if' '(' e=cond ')' s1=stmt ('else' s2=stmt)?
             {$s = new StmtIf($e.e, $s1.s, $s2.s);}
      ;
  </code></pre>
  
  <p>NOTE: question <a href="https://stackoverflow.com/questions/16392152">16392152</a> provides a solution to this question with listeners, but I am not using listeners, my requirement is for this to be handled in the action code.</p>