closure_ method

void closure_(
  1. ATNConfig config,
  2. ATNConfigSet configs,
  3. Set<ATNConfig> closureBusy,
  4. bool collectPredicates,
  5. bool fullCtx,
  6. int depth,
  7. bool treatEofAsEpsilon,
)

Do the actual work of walking epsilon edges */

Implementation

void closure_(
    ATNConfig config,
    ATNConfigSet configs,
    Set<ATNConfig> closureBusy,
    bool collectPredicates,
    bool fullCtx,
    int depth,
    bool treatEofAsEpsilon) {
  final p = config.state;
  // optimization
  if (!p.onlyHasEpsilonTransitions()) {
    configs.add(config, mergeCache);
    // make sure to not return here, because EOF transitions can act as
    // both epsilon transitions and non-epsilon transitions.
//            if ( debug ) log("added config "+configs);
  }

  for (var i = 0; i < p.numberOfTransitions; i++) {
    if (i == 0 && canDropLoopEntryEdgeInLeftRecursiveRule(config)) continue;

    final t = p.transition(i);
    final continueCollecting = (t is! ActionTransition) && collectPredicates;
    final c = getEpsilonTarget(config, t, continueCollecting, depth == 0,
        fullCtx, treatEofAsEpsilon);
    if (c != null) {
      var newDepth = depth;
      if (config.state is RuleStopState) {
        assert(!fullCtx);
        // target fell off end of rule; mark resulting c as having dipped into outer context
        // We can't get here if incoming config was rule stop and we had context
        // track how far we dip into outer context.  Might
        // come in handy and we avoid evaluating context dependent
        // preds if this is > 0.

        if (_dfa != null && _dfa!.isPrecedenceDfa()) {
          final outermostPrecedenceReturn =
              (t as EpsilonTransition).outermostPrecedenceReturn;
          if (outermostPrecedenceReturn == _dfa!.atnStartState!.ruleIndex) {
            c.setPrecedenceFilterSuppressed(true);
          }
        }

        c.reachesIntoOuterContext++;

        if (!closureBusy.add(c)) {
          // avoid infinite recursion for right-recursive rules
          continue;
        }

        // TODO: can remove? only care when we add to set per middle of this method
        configs.dipsIntoOuterContext = true;
//          assert(newDepth > int.MIN_VALUE);
        newDepth--;
        if (debug) log('dips into outer ctx: $c');
      } else {
        if (!t.isEpsilon && !closureBusy.add(c)) {
          // avoid infinite recursion for EOF* and EOF+
          continue;
        }

        if (t is RuleTransition) {
          // latch when newDepth goes negative - once we step out of the entry context we can't return
          if (newDepth >= 0) {
            newDepth++;
          }
        }
      }

      closureCheckingStopState(
        c,
        configs,
        closureBusy,
        continueCollecting,
        fullCtx,
        newDepth,
        treatEofAsEpsilon,
      );
    }
  }
}