public ATN createATN() {
   _createATN(g.rules.values());
   atn.maxTokenType = g.getMaxTokenType();
   addRuleFollowLinks();
   addEOFTransitionToStartRules();
   return atn;
 }
  public ParserATNFactory(@NotNull Grammar g) {
    if (g == null) {
      throw new NullPointerException("g");
    }

    this.g = g;

    ATNType atnType = g instanceof LexerGrammar ? ATNType.LEXER : ATNType.PARSER;
    int maxTokenType = g.getMaxTokenType();
    this.atn = new ATN(atnType, maxTokenType);
  }
  @NotNull
  @Override
  public ATN createATN() {
    _createATN(g.rules.values());
    assert atn.maxTokenType == g.getMaxTokenType();
    addRuleFollowLinks();
    addEOFTransitionToStartRules();
    ATNOptimizer.optimize(g, atn);

    for (Triple<Rule, ATNState, ATNState> pair : preventEpsilonClosureBlocks) {
      LL1Analyzer analyzer = new LL1Analyzer(atn);
      if (analyzer.LOOK(pair.b, pair.c, null).contains(org.antlr.v4.runtime.Token.EPSILON)) {
        ErrorType errorType =
            pair.a instanceof LeftRecursiveRule
                ? ErrorType.EPSILON_LR_FOLLOW
                : ErrorType.EPSILON_CLOSURE;
        g.tool.errMgr.grammarError(
            errorType, g.fileName, ((GrammarAST) pair.a.ast.getChild(0)).getToken(), pair.a.name);
      }
    }

    optionalCheck:
    for (Triple<Rule, ATNState, ATNState> pair : preventEpsilonOptionalBlocks) {
      int bypassCount = 0;
      for (int i = 0; i < pair.b.getNumberOfTransitions(); i++) {
        ATNState startState = pair.b.transition(i).target;
        if (startState == pair.c) {
          bypassCount++;
          continue;
        }

        LL1Analyzer analyzer = new LL1Analyzer(atn);
        if (analyzer.LOOK(startState, pair.c, null).contains(org.antlr.v4.runtime.Token.EPSILON)) {
          g.tool.errMgr.grammarError(
              ErrorType.EPSILON_OPTIONAL,
              g.fileName,
              ((GrammarAST) pair.a.ast.getChild(0)).getToken(),
              pair.a.name);
          continue optionalCheck;
        }
      }

      if (bypassCount != 1) {
        throw new UnsupportedOperationException(
            "Expected optional block with exactly 1 bypass alternative.");
      }
    }

    return atn;
  }
 /**
  * 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);
 }