/** * From {@code (A)?} build either: * * <pre> * o--A->o * | ^ * o---->| * </pre> * * or, if {@code A} is a block, just add an empty alt to the end of the block */ @Override public Handle optional(GrammarAST optAST, Handle blk) { BlockStartState blkStart = (BlockStartState) blk.left; ATNState blkEnd = blk.right; preventEpsilonOptionalBlocks.add( new Triple<Rule, ATNState, ATNState>(currentRule, blkStart, blkEnd)); boolean greedy = ((QuantifierAST) optAST).isGreedy(); blkStart.nonGreedy = !greedy; epsilon(blkStart, blk.right, !greedy); optAST.atnState = blk.left; return blk; }
protected Handle makeBlock(BlockStartState start, GrammarAST blkAST, List<Handle> alts) { BlockEndState end = newState(BlockEndState.class, blkAST); start.endState = end; for (Handle alt : alts) { // hook alts up to decision block epsilon(start, alt.left); epsilon(alt.right, end); // no back link in ATN so must walk entire alt to see if we can // strip out the epsilon to 'end' state TailEpsilonRemover opt = new TailEpsilonRemover(); opt.visit(alt.left); } Handle h = new Handle(start, end); // FASerializer ser = new FASerializer(g, h.left); // System.out.println(blkAST.toStringTree()+":\n"+ser); blkAST.atnState = start; return h; }