public static PredictionContext GetCachedContext(PredictionContext context, PredictionContextCache contextCache, PredictionContext.IdentityHashMap visited) { if (context.IsEmpty) { return(context); } PredictionContext existing = visited.Get(context); if (existing != null) { return(existing); } existing = contextCache.Get(context); if (existing != null) { visited.Put(context, existing); return(existing); } bool changed = false; PredictionContext[] parents = new PredictionContext[context.Size]; for (int i = 0; i < parents.Length; i++) { PredictionContext parent = GetCachedContext(context.GetParent(i), contextCache, visited); if (changed || parent != context.GetParent(i)) { if (!changed) { parents = new PredictionContext[context.Size]; for (int j = 0; j < context.Size; j++) { parents[j] = context.GetParent(j); } changed = true; } parents[i] = parent; } } if (!changed) { contextCache.Add(context); visited.Put(context, context); return(context); } PredictionContext updated; if (parents.Length == 0) { updated = EMPTY; } else if (parents.Length == 1) { updated = SingletonPredictionContext.Create(parents[0], context.GetReturnState(0)); } else { ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context; updated = new ArrayPredictionContext(parents, arrayPredictionContext.returnStates); } contextCache.Add(updated); visited.Put(updated, updated); visited.Put(context, updated); return(updated); }
public virtual string[] ToStrings(IRecognizer recognizer, PredictionContext stop, int currentState) { List <string> result = new List <string>(); for (int perm = 0; ; perm++) { int offset = 0; bool last = true; PredictionContext p = this; int stateNumber = currentState; StringBuilder localBuffer = new StringBuilder(); localBuffer.Append("["); while (!p.IsEmpty && p != stop) { int index = 0; if (p.Size > 0) { int bits = 1; while ((1 << bits) < p.Size) { bits++; } int mask = (1 << bits) - 1; index = (perm >> offset) & mask; last &= index >= p.Size - 1; if (index >= p.Size) { goto outer_continue; } offset += bits; } if (recognizer != null) { if (localBuffer.Length > 1) { // first char is '[', if more than that this isn't the first rule localBuffer.Append(' '); } ATN atn = recognizer.Atn; ATNState s = atn.states[stateNumber]; string ruleName = recognizer.RuleNames[s.ruleIndex]; localBuffer.Append(ruleName); } else { if (p.GetReturnState(index) != EMPTY_RETURN_STATE) { if (!p.IsEmpty) { if (localBuffer.Length > 1) { // first char is '[', if more than that this isn't the first rule localBuffer.Append(' '); } localBuffer.Append(p.GetReturnState(index)); } } } stateNumber = p.GetReturnState(index); p = p.GetParent(index); } localBuffer.Append("]"); result.Add(localBuffer.ToString()); if (last) { break; } outer_continue :; } return(result.ToArray()); }
/// <summary> /// Compute set of tokens that can follow /// <paramref name="s"/> /// in the ATN in the /// specified /// <paramref name="ctx"/> /// . /// <p/> /// If /// <paramref name="ctx"/> /// is /// <see cref="PredictionContext.EMPTY"/> /// and /// <paramref name="stopState"/> /// or the end of the rule containing /// <paramref name="s"/> /// is reached, /// <see cref="TokenConstants.EPSILON"/> /// is added to the result set. If /// <paramref name="ctx"/> /// is not /// <see cref="PredictionContext.EMPTY"/> /// and /// <paramref name="addEOF"/> /// is /// <see langword="true"/> /// and /// <paramref name="stopState"/> /// or the end of the outermost rule is reached, /// <see cref="TokenConstants.EOF"/> /// is added to the result set. /// </summary> /// <param name="s">the ATN state.</param> /// <param name="stopState"> /// the ATN state to stop at. This can be a /// <see cref="BlockEndState"/> /// to detect epsilon paths through a closure. /// </param> /// <param name="ctx"> /// The outer context, or /// <see cref="PredictionContext.EMPTY"/> /// if /// the outer context should not be used. /// </param> /// <param name="look">The result lookahead set.</param> /// <param name="lookBusy"> /// A set used for preventing epsilon closures in the ATN /// from causing a stack overflow. Outside code should pass /// <c>new HashSet<ATNConfig></c> /// for this argument. /// </param> /// <param name="calledRuleStack"> /// A set used for preventing left recursion in the /// ATN from causing a stack overflow. Outside code should pass /// <c>new BitSet()</c> /// for this argument. /// </param> /// <param name="seeThruPreds"> /// /// <see langword="true"/> /// to true semantic predicates as /// implicitly /// <see langword="true"/> /// and "see through them", otherwise /// <see langword="false"/> /// to treat semantic predicates as opaque and add /// <see cref="HitPred"/> /// to the /// result if one is encountered. /// </param> /// <param name="addEOF"> /// Add /// <see cref="TokenConstants.EOF"/> /// to the result if the end of the /// outermost context is reached. This parameter has no effect if /// <paramref name="ctx"/> /// is /// <see cref="PredictionContext.EMPTY"/> /// . /// </param> protected internal virtual void Look(ATNState s, ATNState stopState, PredictionContext ctx, IntervalSet look, HashSet <ATNConfig> lookBusy, BitSet calledRuleStack, bool seeThruPreds, bool addEOF) { // System.out.println("_LOOK("+s.stateNumber+", ctx="+ctx); ATNConfig c = new ATNConfig(s, 0, ctx); if (!lookBusy.Add(c)) { return; } if (s == stopState) { if (ctx == null) { look.Add(TokenConstants.EPSILON); return; } else if (ctx.IsEmpty && addEOF) { look.Add(TokenConstants.EOF); return; } } if (s is RuleStopState) { if (ctx == null) { look.Add(TokenConstants.EPSILON); return; } else if (ctx.IsEmpty && addEOF) { look.Add(TokenConstants.EOF); return; } if (ctx != PredictionContext.EMPTY) { for (int i = 0; i < ctx.Size; i++) { ATNState returnState = atn.states[ctx.GetReturnState(i)]; bool removed = calledRuleStack.Get(returnState.ruleIndex); try { calledRuleStack.Clear(returnState.ruleIndex); Look(returnState, stopState, ctx.GetParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF); } finally { if (removed) { calledRuleStack.Set(returnState.ruleIndex); } } } return; } } int n = s.NumberOfTransitions; for (int i_1 = 0; i_1 < n; i_1++) { Transition t = s.Transition(i_1); if (t is RuleTransition) { RuleTransition ruleTransition = (RuleTransition)t; if (calledRuleStack.Get(ruleTransition.ruleIndex)) { continue; } PredictionContext newContext = SingletonPredictionContext.Create(ctx, ruleTransition.followState.stateNumber); try { calledRuleStack.Set(ruleTransition.target.ruleIndex); Look(t.target, stopState, newContext, look, lookBusy, calledRuleStack, seeThruPreds, addEOF); } finally { calledRuleStack.Clear(ruleTransition.target.ruleIndex); } } else { if (t is AbstractPredicateTransition) { if (seeThruPreds) { Look(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF); } else { look.Add(HitPred); } } else { if (t.IsEpsilon) { Look(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF); } else { if (t is WildcardTransition) { look.AddAll(IntervalSet.Of(TokenConstants.MinUserTokenType, atn.maxTokenType)); } else { IntervalSet set = t.Label; if (set != null) { if (t is NotSetTransition) { set = set.Complement(IntervalSet.Of(TokenConstants.MinUserTokenType, atn.maxTokenType)); } look.AddAll(set); } } } } } } }