@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); } } } } }
public void addRuleFollowLinks() { for (ATNState p : atn.states) { if (p != null && p.getStateType() == ATNState.BASIC && p.getNumberOfTransitions() == 1 && p.transition(0) instanceof RuleTransition) { RuleTransition rt = (RuleTransition) p.transition(0); addFollowLink(rt.ruleIndex, rt.followState); } } }
/** * 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; }
protected void epsilon(ATNState a, @NotNull ATNState b, boolean prepend) { if (a != null) { int index = prepend ? 0 : a.getNumberOfTransitions(); a.addTransition(index, new EpsilonTransition(b)); } }