protected void Closure_(ATNConfig config,
ATNConfigSet configs,
HashSet<ATNConfig> closureBusy,
bool collectPredicates,
bool fullCtx,
int depth,
bool treatEofAsEpsilon)
{
ATNState 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 ) Console.WriteLine("added config "+configs);
}
for (int i = 0; i < p.NumberOfTransitions; i++)
{
if (i == 0 && CanDropLoopEntryEdgeInLeftRecursiveRule(config)) continue;
Transition t = p.Transition(i);
bool continueCollecting =
!(t is ActionTransition) && collectPredicates;
ATNConfig c = GetEpsilonTarget(config, t, continueCollecting,
depth == 0, fullCtx, treatEofAsEpsilon);
if (c != null)
{
if (!t.IsEpsilon && !closureBusy.Add(c))
{
// avoid infinite recursion for EOF* and EOF+
continue;
}
int newDepth = depth;
if (config.state is RuleStopState)
{
// 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 (!closureBusy.Add(c))
{
// avoid infinite recursion for right-recursive rules
continue;
}
if (thisDfa != null && thisDfa.IsPrecedenceDfa)
{
int outermostPrecedenceReturn = ((EpsilonTransition)t).OutermostPrecedenceReturn;
if (outermostPrecedenceReturn == thisDfa.atnStartState.ruleIndex)
{
c.SetPrecedenceFilterSuppressed(true);
}
}
c.reachesIntoOuterContext++;
configs.dipsIntoOuterContext = true; // TODO: can remove? only care when we add to set per middle of this method
newDepth--;
if (debug)
Console.WriteLine("dips into outer ctx: " + c);
}
else 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);
}
}
}