@NotNull public ATNState newState(@Nullable GrammarAST node) { ATNState n = new ATNState(); n.setRuleIndex(currentRule.index); atn.addState(n); return n; }
/** Build an atom with all possible values in its label */ @NotNull public Handle wildcard(GrammarAST node) { ATNState left = newState(node); ATNState right = newState(node); left.addTransition(new WildcardTransition(right)); node.atnState = left; return new Handle(left, right); }
/** From label A build Graph o-A->o */ public Handle tokenRef(TerminalAST node) { ATNState left = newState(node); ATNState right = newState(node); int ttype = g.getTokenType(node.getText()); left.addTransition(new AtomTransition(right, ttype)); node.atnState = left; return new Handle(left, right); }
/** * Build what amounts to an epsilon transition with an action. The action goes into ATN though it * is ignored during prediction if actionIndex < 0. Only forced are executed during prediction. */ public Handle action(ActionAST action) { // System.out.println("action: "+action); ATNState left = newState(action); ATNState right = newState(action); ActionTransition a = new ActionTransition(right, currentRule.index); left.addTransition(a); action.atnState = left; return new Handle(left, right); }
public void addRuleFollowLinks() { for (ATNState p : atn.states) { if (p != null && p.getClass() == ATNState.class && p.getNumberOfTransitions() == 1 && p.transition(0) instanceof RuleTransition) { RuleTransition rt = (RuleTransition) p.transition(0); addFollowLink(rt.ruleIndex, rt.followState); } } }
/** * Build what amounts to an epsilon transition with a semantic predicate action. The pred is a * pointer into the AST of the SEMPRED token. */ public Handle sempred(PredAST pred) { // System.out.println("sempred: "+ pred); ATNState left = newState(pred); ATNState right = newState(pred); boolean isCtxDependent = UseDefAnalyzer.actionIsContextDependent(pred); PredicateTransition p = new PredicateTransition(right, currentRule.index, g.sempreds.get(pred), isCtxDependent); left.addTransition(p); pred.atnState = left; return new Handle(left, right); }
/** * add an EOF transition to any rule end ATNState that points to nothing (i.e., for all those * rules not invoked by another rule). These are start symbols then. * * <p>Return the number of grammar entry points; i.e., how many rules are not invoked by another * rule (they can only be invoked from outside). These are the start rules. */ public int addEOFTransitionToStartRules() { int n = 0; ATNState eofTarget = newState(null); // one unique EOF target for all rules for (Rule r : g.rules.values()) { ATNState stop = atn.ruleToStopState[r.index]; if (stop.getNumberOfTransitions() > 0) continue; n++; Transition t = new AtomTransition(eofTarget, Token.EOF); stop.addTransition(t); } return n; }
public Handle _ruleRef(GrammarAST node) { Rule r = g.getRule(node.getText()); if (r == null) { g.tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, "Rule " + node.getText() + " undefined"); return null; } RuleStartState start = atn.ruleToStartState[r.index]; ATNState left = newState(node); ATNState right = newState(node); RuleTransition call = new RuleTransition(start, r.index, right); left.addTransition(call); node.atnState = left; return new Handle(left, right); }
/** * From set build single edge graph o->o-set->o. To conform to what an alt block looks like, must * have extra state on left. This handles ~A also, converted to ~{A} set. */ public Handle set(GrammarAST associatedAST, List<GrammarAST> terminals, boolean invert) { ATNState left = newState(associatedAST); ATNState right = newState(associatedAST); IntervalSet set = new IntervalSet(); for (GrammarAST t : terminals) { int ttype = g.getTokenType(t.getText()); set.add(ttype); } if (invert) { IntervalSet notSet = set.complement(Token.MIN_TOKEN_TYPE, g.getMaxTokenType()); left.addTransition(new NotSetTransition(right, set, notSet)); } else { left.addTransition(new SetTransition(right, set)); } associatedAST.atnState = left; return new Handle(left, right); }
@Override public void visitState(ATNState p) { if (p.getClass() == ATNState.class && p.getNumberOfTransitions() == 1) { ATNState q = p.transition(0).target; if (p.transition(0) instanceof RuleTransition) { q = ((RuleTransition) p.transition(0)).followState; } if (q.getClass() == ATNState.class) { // we have p-x->q for x in {rule, action, pred, token, ...} // if edge out of q is single epsilon to block end // we can strip epsilon p-x->q-eps->r Transition trans = q.transition(0); if (q.getNumberOfTransitions() == 1 && trans.isEpsilon() && !(trans instanceof ActionTransition)) { ATNState r = trans.target; if (r instanceof BlockEndState || r instanceof PlusLoopbackState || r instanceof StarLoopbackState) { // skip over q if (p.transition(0) instanceof RuleTransition) { ((RuleTransition) p.transition(0)).followState = r; } else { p.transition(0).target = r; } atn.removeState(q); } } } } }
void epsilon(ATNState a, @NotNull ATNState b) { if (a != null) a.addTransition(new EpsilonTransition(b)); }