closure method
bool
closure(
- CharStream input,
- LexerATNConfig config,
- ATNConfigSet configs,
- bool currentAltReachedAcceptState,
- bool speculative,
- bool treatEofAsEpsilon,
Since the alternatives within any lexer decision are ordered by
preference, this method stops pursuing the closure as soon as an accept
state is reached. After the first accept state is reached by depth-first
search from config
, all other (potentially reachable) states for
this rule would have a lower priority.
@return true
if an accept state is reached, otherwise
false
.
Implementation
bool closure(
CharStream input,
LexerATNConfig config,
ATNConfigSet configs,
bool currentAltReachedAcceptState,
bool speculative,
bool treatEofAsEpsilon) {
if (debug) {
log('closure(' + config.toString(recog, true) + ')',
level: Level.FINE.value);
}
if (config.state is RuleStopState) {
if (debug) {
log('closure at ${recog.ruleNames[config.state.ruleIndex]} rule stop $config\n',
level: Level.FINE.value);
}
if (config.context == null || config.context!.hasEmptyPath()) {
if (config.context == null || config.context!.isEmpty) {
configs.add(config);
return true;
} else {
configs.add(LexerATNConfig.dup(
config,
config.state,
context: EmptyPredictionContext.Instance,
));
currentAltReachedAcceptState = true;
}
}
if (config.context != null && !config.context!.isEmpty) {
for (var i = 0; i < config.context!.length; i++) {
if (config.context!.getReturnState(i) !=
PredictionContext.EMPTY_RETURN_STATE) {
final newContext =
config.context!.getParent(i); // "pop" return state
final returnState = atn.states[config.context!.getReturnState(i)]!;
final c =
LexerATNConfig.dup(config, returnState, context: newContext);
currentAltReachedAcceptState = closure(
input,
c,
configs,
currentAltReachedAcceptState,
speculative,
treatEofAsEpsilon,
);
}
}
}
return currentAltReachedAcceptState;
}
// optimization
if (!config.state.onlyHasEpsilonTransitions()) {
if (!currentAltReachedAcceptState ||
!config.hasPassedThroughNonGreedyDecision()) {
configs.add(config);
}
}
final p = config.state;
for (var i = 0; i < p.numberOfTransitions; i++) {
final t = p.transition(i);
final c = getEpsilonTarget(
input,
config,
t,
configs,
speculative,
treatEofAsEpsilon,
);
if (c != null) {
currentAltReachedAcceptState = closure(input, c, configs,
currentAltReachedAcceptState, speculative, treatEofAsEpsilon);
}
}
return currentAltReachedAcceptState;
}