/** * From {@code A|B|..|Z} alternative block build * * <pre> * o->o-A->o->o (last ATNState is BlockEndState pointed to by all alts) * | ^ * |->o-B->o--| * | | * ... | * | | * |->o-Z->o--| * </pre> * * So start node points at every alternative with epsilon transition and every alt right side * points at a block end ATNState. * * <p>Special case: only one alternative: don't make a block with alt begin/end. * * <p>Special case: if just a list of tokens/chars/sets, then collapse to a single edged o-set->o * graph. * * <p>TODO: Set alt number (1..n) in the states? */ @NotNull @Override public Handle block( @NotNull BlockAST blkAST, @NotNull GrammarAST ebnfRoot, @NotNull List<Handle> alts) { if (ebnfRoot == null) { if (alts.size() == 1) { Handle h = alts.get(0); blkAST.atnState = h.left; return h; } BlockStartState start = newState(BasicBlockStartState.class, blkAST); if (alts.size() > 1) atn.defineDecisionState(start); return makeBlock(start, blkAST, alts); } switch (ebnfRoot.getType()) { case ANTLRParser.OPTIONAL: BlockStartState start = newState(BasicBlockStartState.class, blkAST); atn.defineDecisionState(start); Handle h = makeBlock(start, blkAST, alts); return optional(ebnfRoot, h); case ANTLRParser.CLOSURE: BlockStartState star = newState(StarBlockStartState.class, ebnfRoot); if (alts.size() > 1) atn.defineDecisionState(star); h = makeBlock(star, blkAST, alts); return star(ebnfRoot, h); case ANTLRParser.POSITIVE_CLOSURE: PlusBlockStartState plus = newState(PlusBlockStartState.class, ebnfRoot); if (alts.size() > 1) atn.defineDecisionState(plus); h = makeBlock(plus, blkAST, alts); return plus(ebnfRoot, h); } return null; }
public boolean isGreedy(@NotNull BlockAST blkAST) { boolean greedy = true; String greedyOption = blkAST.getOptionString("greedy"); if (blockHasWildcardAlt(blkAST) || greedyOption != null && greedyOption.equals("false")) { greedy = false; } return greedy; }
protected Handle makeBlock(BlockStartState start, BlockAST 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(atn); 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; }
/** * * * <pre> * (RULE e int _p (returns int v) * (BLOCK * (ALT * (BLOCK * (ALT INT {$v = $INT.int;}) * (ALT '(' (= x e) ')' {$v = $x.v;}) * (ALT ID)) * (* (BLOCK * (OPTIONS ...) * (ALT {7 >= $_p}? '*' (= b e) {$v = $a.v * $b.v;}) * (ALT {6 >= $_p}? '+' (= b e) {$v = $a.v + $b.v;}) * (ALT {3 >= $_p}? '++') (ALT {2 >= $_p}? '--')))))) * </pre> */ public void setAltASTPointers(LeftRecursiveRule r, RuleAST t) { // System.out.println("RULE: "+t.toStringTree()); BlockAST ruleBlk = (BlockAST) t.getFirstChildWithType(ANTLRParser.BLOCK); AltAST mainAlt = (AltAST) ruleBlk.getChild(0); BlockAST primaryBlk = (BlockAST) mainAlt.getChild(0); BlockAST opsBlk = (BlockAST) mainAlt.getChild(1).getChild(0); // (* BLOCK ...) for (int i = 0; i < r.recPrimaryAlts.size(); i++) { LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i); altInfo.altAST = (AltAST) primaryBlk.getChild(i); altInfo.altAST.leftRecursiveAltInfo = altInfo; altInfo.originalAltAST.leftRecursiveAltInfo = altInfo; // altInfo.originalAltAST.parent = altInfo.altAST.parent; // System.out.println(altInfo.altAST.toStringTree()); } for (int i = 0; i < r.recOpAlts.size(); i++) { LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i); altInfo.altAST = (AltAST) opsBlk.getChild(i); altInfo.altAST.leftRecursiveAltInfo = altInfo; altInfo.originalAltAST.leftRecursiveAltInfo = altInfo; // altInfo.originalAltAST.parent = altInfo.altAST.parent; // System.out.println(altInfo.altAST.toStringTree()); } }