add method
bool
add(
- ATNConfig config, [
- Map<
Pair< ? mergeCachePredictionContext, PredictionContext> , PredictionContext>
Adding a new config means merging contexts with existing configs for
{@code (s, i, pi, _)}, where s
is the
{@link ATNConfig#state}, i
is the {@link ATNConfig#alt}, and
pi is the {@link ATNConfig#semanticContext}. We use
{@code (s,i,pi)} as key.
This method updates {@link #dipsIntoOuterContext} and {@link #hasSemanticContext} when necessary.
Implementation
bool add(
ATNConfig config, [
Map<Pair<PredictionContext, PredictionContext>, PredictionContext>?
mergeCache,
]) {
if (readOnly) throw StateError('This set is readonly');
if (config.semanticContext != EmptySemanticContext.Instance) {
hasSemanticContext = true;
}
if (config.outerContextDepth > 0) {
dipsIntoOuterContext = true;
}
final existing = configLookup!.lookup(config) ?? config;
if (identical(existing, config)) {
// we added this new one
cachedHashCode = -1;
configLookup!.add(config);
configs.add(config); // track order here
return true;
}
// a previous (s,i,pi,_), merge with it and save result
final rootIsWildcard = !fullCtx;
final merged = PredictionContext.merge(
existing.context!,
config.context!,
rootIsWildcard,
mergeCache,
);
// no need to check for existing.context, config.context in cache
// since only way to create new graphs is "call rule" and here. We
// cache at both places.
existing.reachesIntoOuterContext =
max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext);
// make sure to preserve the precedence filter suppression during the merge
if (config.isPrecedenceFilterSuppressed()) {
existing.setPrecedenceFilterSuppressed(true);
}
existing.context = merged; // replace context; no need to alt mapping
return true;
}