public virtual IntervalSet GetExpectedTokens(int stateNumber, RuleContext context) { if (stateNumber < 0 || stateNumber >= states.Count) { throw new ArgumentException("Invalid state number."); } RuleContext ctx = context; ATNState s = states[stateNumber]; IntervalSet following = NextTokens(s); if (!following.Contains(TokenConstants.EPSILON)) { return(following); } IntervalSet expected = new IntervalSet(); expected.AddAll(following); expected.Remove(TokenConstants.EPSILON); while (ctx != null && ctx.invokingState >= 0 && following.Contains(TokenConstants.EPSILON)) { ATNState invokingState = states[ctx.invokingState]; RuleTransition rt = (RuleTransition)invokingState.Transition(0); following = NextTokens(rt.followState); expected.AddAll(following); expected.Remove(TokenConstants.EPSILON); ctx = ctx.Parent; } if (following.Contains(TokenConstants.EPSILON)) { expected.Add(TokenConstants.EOF); } return(expected); }
public SuggestionState(CaretToken caret, List <FollowList> expected) { Caret = caret ?? throw new ArgumentNullException(nameof(caret)); Expected = expected ?? throw new ArgumentNullException(nameof(expected)); ExpectedTokens = new IntervalSet(); foreach (var item in Expected) { ExpectedTokens.AddAll(item.Tokens); } }
protected internal virtual IntervalSet GetErrorRecoverySet(Parser recognizer) { ATN atn = recognizer.Interpreter.atn; RuleContext ctx = recognizer.RuleContext; IntervalSet recoverSet = new IntervalSet(); while (ctx != null && ctx.invokingState >= 0) { // compute what follows who invoked us ATNState invokingState = atn.states[ctx.invokingState]; RuleTransition rt = (RuleTransition)invokingState.Transition(0); IntervalSet follow = atn.NextTokens(rt.followState); recoverSet.AddAll(follow); ctx = ctx.Parent; } recoverSet.Remove(TokenConstants.Epsilon); // System.out.println("recover set "+recoverSet.toString(recognizer.getTokenNames())); return(recoverSet); }
public IntervalSet Compute(Parser parser, CommonTokenStream token_stream, int line, int col) { _input = new List <IToken>(); _parser = parser; _token_stream = token_stream; _stop_states = new HashSet <ATNState>(); foreach (var s in parser.Atn.ruleToStopState.Select(t => parser.Atn.states[t.stateNumber])) { _stop_states.Add(s); } _start_states = new HashSet <ATNState>(); foreach (var s in parser.Atn.ruleToStartState.Select(t => parser.Atn.states[t.stateNumber])) { _start_states.Add(s); } var currentIndex = _token_stream.Index; _token_stream.Seek(0); var offset = 1; while (true) { var token = _token_stream.LT(offset++); _input.Add(token); _cursor = token.TokenIndex; if (token.Type == TokenConstants.EOF) { break; } if (token.Line >= line && token.Column >= col) { break; } } _token_stream.Seek(currentIndex); List <List <Edge> > all_parses = EnterState(new Edge() { _index = 0, _index_at_transition = 0, _to = _parser.Atn.states[0], _type = TransitionType.EPSILON }); // Remove last token on input. _input.RemoveAt(_input.Count - 1); // Eliminate all paths that don't consume all input. List <List <Edge> > temp = new List <List <Edge> >(); if (all_parses != null) { foreach (var p in all_parses) { //System.Console.Error.WriteLine(PrintSingle(p)); if (Validate(p, _input)) { temp.Add(p); } } } all_parses = temp; if (all_parses != null && this._log_closure) { foreach (var p in all_parses) { System.Console.Error.WriteLine("Path " + PrintSingle(p)); } } var result = new IntervalSet(); if (all_parses != null) { foreach (var p in all_parses) { HashSet <ATNState> set = ComputeSingle(p); if (this._log_closure) { System.Console.Error.WriteLine("All states for path " + String.Join(" ", set.ToList())); } foreach (var s in set) { foreach (var t in s.TransitionsArray) { switch (t.TransitionType) { case TransitionType.RULE: break; case TransitionType.PREDICATE: break; case TransitionType.WILDCARD: break; default: if (!t.IsEpsilon) { result.AddAll(t.Label); } break; } } } } } return(result); }
private static int OptimizeSets(ATN atn, bool preserveOrder) { if (preserveOrder) { // this optimization currently doesn't preserve edge order. return(0); } int removedPaths = 0; IList <DecisionState> decisions = atn.decisionToState; foreach (DecisionState decision in decisions) { IntervalSet setTransitions = new IntervalSet(); for (int i = 0; i < decision.NumberOfOptimizedTransitions; i++) { Transition epsTransition = decision.GetOptimizedTransition(i); if (!(epsTransition is EpsilonTransition)) { continue; } if (epsTransition.target.NumberOfOptimizedTransitions != 1) { continue; } Transition transition = epsTransition.target.GetOptimizedTransition(0); if (!(transition.target is BlockEndState)) { continue; } if (transition is NotSetTransition) { // TODO: not yet implemented continue; } if (transition is AtomTransition || transition is RangeTransition || transition is SetTransition) { setTransitions.Add(i); } } if (setTransitions.Count <= 1) { continue; } IList <Transition> optimizedTransitions = new List <Transition>(); for (int i_1 = 0; i_1 < decision.NumberOfOptimizedTransitions; i_1++) { if (!setTransitions.Contains(i_1)) { optimizedTransitions.Add(decision.GetOptimizedTransition(i_1)); } } ATNState blockEndState = decision.GetOptimizedTransition(setTransitions.MinElement).target.GetOptimizedTransition(0).target; IntervalSet matchSet = new IntervalSet(); for (int i_2 = 0; i_2 < setTransitions.GetIntervals().Count; i_2++) { Interval interval = setTransitions.GetIntervals()[i_2]; for (int j = interval.a; j <= interval.b; j++) { Transition matchTransition = decision.GetOptimizedTransition(j).target.GetOptimizedTransition(0); if (matchTransition is NotSetTransition) { throw new NotSupportedException("Not yet implemented."); } else { matchSet.AddAll(matchTransition.Label); } } } Transition newTransition; if (matchSet.GetIntervals().Count == 1) { if (matchSet.Count == 1) { newTransition = new AtomTransition(blockEndState, matchSet.MinElement); } else { Interval matchInterval = matchSet.GetIntervals()[0]; newTransition = new RangeTransition(blockEndState, matchInterval.a, matchInterval.b); } } else { newTransition = new SetTransition(blockEndState, matchSet); } ATNState setOptimizedState = new BasicState(); setOptimizedState.SetRuleIndex(decision.ruleIndex); atn.AddState(setOptimizedState); setOptimizedState.AddTransition(newTransition); optimizedTransitions.Add(new EpsilonTransition(setOptimizedState)); removedPaths += decision.NumberOfOptimizedTransitions - optimizedTransitions.Count; if (decision.IsOptimized) { while (decision.NumberOfOptimizedTransitions > 0) { decision.RemoveOptimizedTransition(decision.NumberOfOptimizedTransitions - 1); } } foreach (Transition transition_1 in optimizedTransitions) { decision.AddOptimizedTransition(transition_1); } } return(removedPaths); }
public IntervalSet Compute(Parser parser, CommonTokenStream token_stream, int line, int col) { _input = new List <IToken>(); _parser = parser; _token_stream = token_stream; _stop_states = new HashSet <ATNState>(); foreach (var s in parser.Atn.ruleToStopState.Select(t => parser.Atn.states[t.stateNumber])) { _stop_states.Add(s); } _start_states = new HashSet <ATNState>(); foreach (var s in parser.Atn.ruleToStartState.Select(t => parser.Atn.states[t.stateNumber])) { _start_states.Add(s); } var currentIndex = _token_stream.Index; _token_stream.Seek(0); var offset = 1; while (true) { var token = _token_stream.LT(offset++); _input.Add(token); _cursor = token.TokenIndex; if (token.Type == TokenConstants.EOF) { break; } if (token.Line >= line && token.Column >= col) { break; } } var all_parses = EnterState(null); var result = new IntervalSet(); if (all_parses != null) { foreach (var p in all_parses) { HashSet <ATNState> set = ComputeSingle(p); if (this._log_closure) { System.Console.Error.WriteLine("All states for path " + String.Join(" ", set.ToList())); } foreach (var s in set) { foreach (var t in s.TransitionsArray) { switch (t.TransitionType) { case TransitionType.RULE: break; case TransitionType.PREDICATE: break; case TransitionType.WILDCARD: break; default: if (!t.IsEpsilon) { result.AddAll(t.Label); } break; } } } } } return(result); }
/// <summary> /// Walks the ATN for a single rule only. It returns the token stream position for each path that could be matched in this rule. /// The result can be empty in case we hit only non-epsilon transitions that didn't match the current input or if we /// hit the caret position. /// </summary> private ISet <int> ProcessRule(ATNState startState, int tokenIndex, LinkedList <int> callStack, string indentation) { // Start with rule specific handling before going into the ATN walk. // Check first if we've taken this path with the same input before. if (!this.shortcutMap.TryGetValue(startState.ruleIndex, out var positionMap)) { positionMap = new Dictionary <int, ISet <int> >(); this.shortcutMap[startState.ruleIndex] = positionMap; } else { if (positionMap.ContainsKey(tokenIndex)) { return(positionMap[tokenIndex]); } } var result = new HashSet <int>(); // For rule start states we determine and cache the follow set, which gives us 3 advantages: // 1) We can quickly check if a symbol would be matched when we follow that rule. We can so check in advance // and can save us all the intermediate steps if there is no match. // 2) We'll have all symbols that are collectable already together when we are at the caret when entering a rule. // 3) We get this lookup for free with any 2nd or further visit of the same rule, which often happens // in non trivial grammars, especially with (recursive) expressions and of course when invoking code completion // multiple times. if (!this.followSetsByATN.TryGetValue(this.parser.GetType().Name, out var setsPerState)) { setsPerState = new FollowSetsPerState(); this.followSetsByATN[this.parser.GetType().Name] = setsPerState; } if (!setsPerState.TryGetValue(startState.stateNumber, out var followSets)) { followSets = new FollowSetsHolder(); setsPerState[startState.stateNumber] = followSets; var stop = this.atn.ruleToStopState[startState.ruleIndex]; followSets.Sets = this.DetermineFollowSets(startState, stop).ToList(); // Sets are split by path to allow translating them to preferred rules. But for quick hit tests // it is also useful to have a set with all symbols combined. var combined = new IntervalSet(); foreach (var set in followSets.Sets) { combined.AddAll(set.Intervals); } followSets.Combined = combined; } callStack.AddLast(startState.ruleIndex); var currentSymbol = this.tokens[tokenIndex].Type; if (tokenIndex >= this.tokens.Count - 1) { // At caret? if (this.preferredRules.Contains(startState.ruleIndex)) { // No need to go deeper when collecting entries and we reach a rule that we want to collect anyway. this.TranslateToRuleIndex(callStack.ToList()); } else { // Convert all follow sets to either single symbols or their associated preferred rule and add // the result to our candidates list. foreach (var set in followSets.Sets) { var fullPath = new LinkedList <int>(callStack); foreach (var item in set.Path) { fullPath.AddLast(item); } if (!this.TranslateToRuleIndex(fullPath.ToList())) { foreach (var symbol in set.Intervals.ToList()) { if (!this.ignoredTokens.Contains(symbol)) { if (!this.candidates.Tokens.ContainsKey(symbol)) { // Following is empty if there is more than one entry in the set. this.candidates.Tokens[symbol] = set.Following; } else { // More than one following list for the same symbol. if (!this.candidates.Tokens[symbol].SequenceEqual(set.Following)) { this.candidates.Tokens[symbol] = new List <int>(); } } } } } } } callStack.RemoveLast(); return(result); } else { // Process the rule if we either could pass it without consuming anything (epsilon transition) // or if the current input symbol will be matched somewhere after this entry point. // Otherwise stop here. if (!followSets.Combined.Contains(TokenConstants.Epsilon) && !followSets.Combined.Contains(currentSymbol)) { callStack.RemoveLast(); return(result); } } // The current state execution pipeline contains all yet-to-be-processed ATN states in this rule. // For each such state we store the token index + a list of rules that lead to it. var statePipeline = new LinkedList <PipelineEntry>(); // Bootstrap the pipeline. statePipeline.AddLast(new PipelineEntry(startState, tokenIndex)); PipelineEntry currentEntry; while (statePipeline.Count() > 0) { currentEntry = statePipeline.Last(); statePipeline.RemoveLast(); ++this.statesProcessed; currentSymbol = this.tokens[currentEntry.TokenIndex].Type; var atCaret = currentEntry.TokenIndex >= this.tokens.Count - 1; switch (currentEntry.State.StateType) { // Happens only for the first state in this rule, not subrules. case StateType.RuleStart: indentation += " "; break; // Record the token index we are at, to report it to the caller. case StateType.RuleStop: result.Add(currentEntry.TokenIndex); continue; default: break; } var transitions = currentEntry.State.Transitions; foreach (var transition in transitions) { switch (transition.TransitionType) { case TransitionType.Rule: { var endStatus = this.ProcessRule(transition.target, currentEntry.TokenIndex, callStack, indentation); foreach (var position in endStatus) { statePipeline.AddLast(new PipelineEntry(((RuleTransition)transition).followState, position)); } break; } case TransitionType.Predicate: { if (this.CheckPredicate((PredicateTransition)transition)) { statePipeline.AddLast(new PipelineEntry(transition.target, currentEntry.TokenIndex)); } break; } case TransitionType.Wildcard: { if (atCaret) { if (!this.TranslateToRuleIndex(callStack.ToList())) { foreach (var token in IntervalSet.Of(TokenConstants.MinUserTokenType, this.atn.maxTokenType).ToList()) { if (!this.ignoredTokens.Contains(token)) { this.candidates.Tokens[token] = new List <int>(); } } } } else { statePipeline.AddLast(new PipelineEntry(transition.target, currentEntry.TokenIndex + 1)); } break; } default: { if (transition.IsEpsilon) { // Jump over simple states with a single outgoing epsilon transition. statePipeline.AddLast(new PipelineEntry(transition.target, currentEntry.TokenIndex)); continue; } var set = transition.Label; if (set != null && set.Count > 0) { if (transition.TransitionType == TransitionType.NotSet) { set = set.Complement(IntervalSet.Of(TokenConstants.MinUserTokenType, this.atn.maxTokenType)); } if (atCaret) { if (!this.TranslateToRuleIndex(callStack.ToList())) { var list = set.ToList(); var isAddFollowing = list.Count == 1; foreach (var symbol in list) { if (!this.ignoredTokens.Contains(symbol)) { if (isAddFollowing) { this.candidates.Tokens[symbol] = this.GetFollowingTokens(transition); } else { this.candidates.Tokens[symbol] = new List <int>(); } } } } } else { if (set.Contains(currentSymbol)) { statePipeline.AddLast(new PipelineEntry(transition.target, currentEntry.TokenIndex + 1)); } } } } break; } } } callStack.RemoveLast(); // Cache the result, for later lookup to avoid duplicate walks. positionMap[tokenIndex] = result; return(result); }
/// <summary> /// Compute set of tokens that can follow /// <code>s</code> /// in the ATN in the /// specified /// <code>ctx</code> /// . /// <p/> /// If /// <code>ctx</code> /// is /// <see cref="PredictionContext.EmptyLocal">PredictionContext.EmptyLocal</see> /// and /// <code>stopState</code> /// or the end of the rule containing /// <code>s</code> /// is reached, /// <see cref="TokenConstants.Epsilon"/> /// is added to the result set. If /// <code>ctx</code> /// is not /// <see cref="PredictionContext.EmptyLocal">PredictionContext.EmptyLocal</see> /// and /// <code>addEOF</code> /// is /// <code>true</code> /// and /// <code>stopState</code> /// 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">BlockEndState</see> /// to detect epsilon paths through a closure. /// </param> /// <param name="ctx"> /// The outer context, or /// <see cref="PredictionContext.EmptyLocal">PredictionContext.EmptyLocal</see> /// 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 /// <code>new HashSet<ATNConfig></code> /// 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 /// <code>new BitSet()</code> /// for this argument. /// </param> /// <param name="seeThruPreds"> /// /// <code>true</code> /// to true semantic predicates as /// implicitly /// <code>true</code> /// and "see through them", otherwise /// <code>false</code> /// to treat semantic predicates as opaque and add /// <see cref="HitPred">HitPred</see> /// 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 /// <code>ctx</code> /// is /// <see cref="PredictionContext.EmptyLocal">PredictionContext.EmptyLocal</see> /// . /// </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 = ATNConfig.Create(s, 0, ctx); if (!lookBusy.Add(c)) { return; } if (s == stopState) { if (PredictionContext.IsEmptyLocal(ctx)) { look.Add(TokenConstants.Epsilon); return; } else { if (ctx.IsEmpty && addEOF) { look.Add(TokenConstants.Eof); return; } } } if (s is RuleStopState) { if (PredictionContext.IsEmptyLocal(ctx)) { look.Add(TokenConstants.Epsilon); return; } else { if (ctx.IsEmpty && addEOF) { look.Add(TokenConstants.Eof); return; } } for (int i = 0; i < ctx.Size; i++) { if (ctx.GetReturnState(i) != PredictionContext.EmptyFullStateKey) { ATNState returnState = atn.states[ctx.GetReturnState(i)]; // System.out.println("popping back to "+retState); for (int j = 0; j < ctx.Size; j++) { bool removed = calledRuleStack.Get(returnState.ruleIndex); try { calledRuleStack.Clear(returnState.ruleIndex); Look(returnState, stopState, ctx.GetParent(j), 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.GetType() == typeof(RuleTransition)) { if (calledRuleStack.Get(((RuleTransition)t).target.ruleIndex)) { continue; } PredictionContext newContext = ctx.GetChild(((RuleTransition)t).followState.stateNumber ); try { calledRuleStack.Set(((RuleTransition)t).target.ruleIndex); Look(t.target, stopState, newContext, look, lookBusy, calledRuleStack, seeThruPreds , addEOF); } finally { calledRuleStack.Clear(((RuleTransition)t).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.GetType() == typeof(WildcardTransition)) { look.AddAll(IntervalSet.Of(TokenConstants.MinUserTokenType, atn.maxTokenType)); } else { // System.out.println("adding "+ t); IntervalSet set = t.Label; if (set != null) { if (t is NotSetTransition) { set = set.Complement(IntervalSet.Of(TokenConstants.MinUserTokenType, atn.maxTokenType )); } look.AddAll(set); } } } } } } }
/// <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.EmptyLocal"/> /// 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.EmptyLocal"/> /// 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.EmptyLocal"/> /// 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.EmptyLocal"/> /// . /// </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); } } } } } } }
public IntervalSet Compute(Parser parser, CommonTokenStream token_stream) { _input = new List <IToken>(); _parser = parser; _token_stream = token_stream; //_cursor = _token_stream.GetTokens().Select(t => t.Text == "." ? t.TokenIndex : 0).Max(); _stop_states = new HashSet <ATNState>(); foreach (ATNState s in parser.Atn.ruleToStopState.Select(t => parser.Atn.states[t.stateNumber])) { _stop_states.Add(s); } _start_states = new HashSet <ATNState>(); foreach (ATNState s in parser.Atn.ruleToStartState.Select(t => parser.Atn.states[t.stateNumber])) { _start_states.Add(s); } int currentIndex = _token_stream.Index; _token_stream.Seek(0); int offset = 1; while (true) { IToken token = _token_stream.LT(offset++); _input.Add(token); if (token.Type == TokenConstants.EOF) { break; } _cursor = token.TokenIndex; } List <List <Edge> > all_parses = EnterState(null); IntervalSet result = new IntervalSet(); foreach (List <Edge> p in all_parses) { HashSet <ATNState> set = ComputeSingle(p); foreach (ATNState s in set) { foreach (Transition t in s.TransitionsArray) { switch (t.TransitionType) { case TransitionType.RULE: break; case TransitionType.PREDICATE: break; case TransitionType.WILDCARD: break; default: if (!t.IsEpsilon) { result.AddAll(t.Label); } break; } } } } return(result); }