closure_ method
void
closure_()
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,
);
}
}
}