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); }
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; }
/// <summary> /// Serialize state descriptors, edge descriptors, and decision→state map /// into list of ints: /// grammar-type, (ANTLRParser.LEXER, ...) /// max token type, /// num states, /// state-0-type ruleIndex, state-1-type ruleIndex, ... /// </summary> /// <remarks> /// Serialize state descriptors, edge descriptors, and decision→state map /// into list of ints: /// grammar-type, (ANTLRParser.LEXER, ...) /// max token type, /// num states, /// state-0-type ruleIndex, state-1-type ruleIndex, ... state-i-type ruleIndex optional-arg ... /// num rules, /// rule-1-start-state rule-1-args, rule-2-start-state rule-2-args, ... /// (args are token type,actionIndex in lexer else 0,0) /// num modes, /// mode-0-start-state, mode-1-start-state, ... (parser has 0 modes) /// num sets /// set-0-interval-count intervals, set-1-interval-count intervals, ... /// num total edges, /// src, trg, edge-type, edge arg1, optional edge arg2 (present always), ... /// num decisions, /// decision-0-start-state, decision-1-start-state, ... /// Convenient to pack into unsigned shorts to make as Java string. /// </remarks> public virtual List <int> Serialize() { List <int> data = new List <int>(); data.Add(ATNDeserializer.SerializedVersion); SerializeUUID(data, ATNDeserializer.SerializedUuid); // convert grammar type to ATN const to avoid dependence on ANTLRParser data.Add((int)(atn.grammarType)); data.Add(atn.maxTokenType); int nedges = 0; IDictionary <IntervalSet, int> setIndices = new Dictionary <IntervalSet, int>(); IList <IntervalSet> sets = new List <IntervalSet>(); // dump states, count edges and collect sets while doing so List <int> nonGreedyStates = new List <int>(); List <int> sllStates = new List <int>(); List <int> precedenceStates = new List <int>(); data.Add(atn.states.Count); foreach (ATNState s in atn.states) { if (s == null) { // might be optimized away data.Add((int)(StateType.InvalidType)); continue; } StateType stateType = s.StateType; if (s is DecisionState) { DecisionState decisionState = (DecisionState)s; if (decisionState.nonGreedy) { nonGreedyStates.Add(s.stateNumber); } if (decisionState.sll) { sllStates.Add(s.stateNumber); } } if (s is RuleStartState && ((RuleStartState)s).isPrecedenceRule) { precedenceStates.Add(s.stateNumber); } data.Add((int)(stateType)); if (s.ruleIndex == -1) { data.Add(char.MaxValue); } else { data.Add(s.ruleIndex); } if (s.StateType == StateType.LoopEnd) { data.Add(((LoopEndState)s).loopBackState.stateNumber); } else { if (s is BlockStartState) { data.Add(((BlockStartState)s).endState.stateNumber); } } if (s.StateType != StateType.RuleStop) { // the deserializer can trivially derive these edges, so there's no need to serialize them nedges += s.NumberOfTransitions; } for (int i = 0; i < s.NumberOfTransitions; i++) { Transition t = s.Transition(i); TransitionType edgeType = Transition.serializationTypes.Get(t.GetType()); if (edgeType == TransitionType.Set || edgeType == TransitionType.NotSet) { SetTransition st = (SetTransition)t; if (!setIndices.ContainsKey(st.set)) { sets.AddItem(st.set); setIndices.Put(st.set, sets.Count - 1); } } } } // non-greedy states data.Add(nonGreedyStates.Size()); for (int i_1 = 0; i_1 < nonGreedyStates.Size(); i_1++) { data.Add(nonGreedyStates.Get(i_1)); } // SLL decisions data.Add(sllStates.Size()); for (int i_2 = 0; i_2 < sllStates.Size(); i_2++) { data.Add(sllStates.Get(i_2)); } // precedence states data.Add(precedenceStates.Size()); for (int i_3 = 0; i_3 < precedenceStates.Size(); i_3++) { data.Add(precedenceStates.Get(i_3)); } int nrules = atn.ruleToStartState.Length; data.Add(nrules); for (int r = 0; r < nrules; r++) { ATNState ruleStartState = atn.ruleToStartState[r]; data.Add(ruleStartState.stateNumber); bool leftFactored = ruleNames[ruleStartState.ruleIndex].IndexOf(ATNSimulator.RuleVariantDelimiter) >= 0; data.Add(leftFactored ? 1 : 0); if (atn.grammarType == ATNType.Lexer) { if (atn.ruleToTokenType[r] == TokenConstants.Eof) { data.Add(char.MaxValue); } else { data.Add(atn.ruleToTokenType[r]); } } } int nmodes = atn.modeToStartState.Count; data.Add(nmodes); if (nmodes > 0) { foreach (ATNState modeStartState in atn.modeToStartState) { data.Add(modeStartState.stateNumber); } } int nsets = sets.Count; data.Add(nsets); foreach (IntervalSet set in sets) { bool containsEof = set.Contains(TokenConstants.Eof); if (containsEof && set.GetIntervals()[0].b == TokenConstants.Eof) { data.Add(set.GetIntervals().Count - 1); } else { data.Add(set.GetIntervals().Count); } data.Add(containsEof ? 1 : 0); foreach (Interval I in set.GetIntervals()) { if (I.a == TokenConstants.Eof) { if (I.b == TokenConstants.Eof) { continue; } else { data.Add(0); } } else { data.Add(I.a); } data.Add(I.b); } } data.Add(nedges); foreach (ATNState s_1 in atn.states) { if (s_1 == null) { // might be optimized away continue; } if (s_1.StateType == StateType.RuleStop) { continue; } for (int i = 0; i_3 < s_1.NumberOfTransitions; i_3++) { Transition t = s_1.Transition(i_3); if (atn.states[t.target.stateNumber] == null) { throw new InvalidOperationException("Cannot serialize a transition to a removed state."); } int src = s_1.stateNumber; int trg = t.target.stateNumber; TransitionType edgeType = Transition.serializationTypes.Get(t.GetType()); int arg1 = 0; int arg2 = 0; int arg3 = 0; switch (edgeType) { case TransitionType.Rule: { trg = ((RuleTransition)t).followState.stateNumber; arg1 = ((RuleTransition)t).target.stateNumber; arg2 = ((RuleTransition)t).ruleIndex; arg3 = ((RuleTransition)t).precedence; break; } case TransitionType.Precedence: { PrecedencePredicateTransition ppt = (PrecedencePredicateTransition)t; arg1 = ppt.precedence; break; } case TransitionType.Predicate: { PredicateTransition pt = (PredicateTransition)t; arg1 = pt.ruleIndex; arg2 = pt.predIndex; arg3 = pt.isCtxDependent ? 1 : 0; break; } case TransitionType.Range: { arg1 = ((RangeTransition)t).from; arg2 = ((RangeTransition)t).to; if (arg1 == TokenConstants.Eof) { arg1 = 0; arg3 = 1; } break; } case TransitionType.Atom: { arg1 = ((AtomTransition)t).label; if (arg1 == TokenConstants.Eof) { arg1 = 0; arg3 = 1; } break; } case TransitionType.Action: { ActionTransition at = (ActionTransition)t; arg1 = at.ruleIndex; arg2 = at.actionIndex; if (arg2 == -1) { arg2 = unchecked ((int)(0xFFFF)); } arg3 = at.isCtxDependent ? 1 : 0; break; } case TransitionType.Set: { arg1 = setIndices.Get(((SetTransition)t).set); break; } case TransitionType.NotSet: { arg1 = setIndices.Get(((SetTransition)t).set); break; } case TransitionType.Wildcard: { break; } } data.Add(src); data.Add(trg); data.Add((int)(edgeType)); data.Add(arg1); data.Add(arg2); data.Add(arg3); } } int ndecisions = atn.decisionToState.Count; data.Add(ndecisions); foreach (DecisionState decStartState in atn.decisionToState) { data.Add(decStartState.stateNumber); } // // LEXER ACTIONS // if (atn.grammarType == ATNType.Lexer) { data.Add(atn.lexerActions.Length); foreach (ILexerAction action in atn.lexerActions) { data.Add((int)(action.GetActionType())); switch (action.GetActionType()) { case LexerActionType.Channel: { int channel = ((LexerChannelAction)action).GetChannel(); data.Add(channel != -1 ? channel : unchecked ((int)(0xFFFF))); data.Add(0); break; } case LexerActionType.Custom: { int ruleIndex = ((LexerCustomAction)action).GetRuleIndex(); int actionIndex = ((LexerCustomAction)action).GetActionIndex(); data.Add(ruleIndex != -1 ? ruleIndex : unchecked ((int)(0xFFFF))); data.Add(actionIndex != -1 ? actionIndex : unchecked ((int)(0xFFFF))); break; } case LexerActionType.Mode: { int mode = ((LexerModeAction)action).GetMode(); data.Add(mode != -1 ? mode : unchecked ((int)(0xFFFF))); data.Add(0); break; } case LexerActionType.More: { data.Add(0); data.Add(0); break; } case LexerActionType.PopMode: { data.Add(0); data.Add(0); break; } case LexerActionType.PushMode: { mode = ((LexerPushModeAction)action).GetMode(); data.Add(mode != -1 ? mode : unchecked ((int)(0xFFFF))); data.Add(0); break; } case LexerActionType.Skip: { data.Add(0); data.Add(0); break; } case LexerActionType.Type: { int type = ((LexerTypeAction)action).GetType(); data.Add(type != -1 ? type : unchecked ((int)(0xFFFF))); data.Add(0); break; } default: { string message = string.Format(CultureInfo.CurrentCulture, "The specified lexer action type {0} is not valid.", action.GetActionType()); throw new ArgumentException(message); } } } } // don't adjust the first value since that's the version number for (int i_4 = 1; i_4 < data.Size(); i_4++) { if (data.Get(i_4) < char.MinValue || data.Get(i_4) > char.MaxValue) { throw new NotSupportedException("Serialized ATN data element out of range."); } int value = (data.Get(i_4) + 2) & unchecked ((int)(0xFFFF)); data.Set(i_4, value); } return(data); }
public override Handle Set(GrammarAST associatedAST, IList<GrammarAST> alts, bool invert) { ATNState left = NewState(associatedAST); ATNState right = NewState(associatedAST); IntervalSet set = new IntervalSet(); foreach (GrammarAST t in alts) { if (t.Type == ANTLRParser.RANGE) { int a = CharSupport.GetCharValueFromGrammarCharLiteral(t.GetChild(0).Text); int b = CharSupport.GetCharValueFromGrammarCharLiteral(t.GetChild(1).Text); if (CheckRange((GrammarAST)t.GetChild(0), (GrammarAST)t.GetChild(1), a, b)) { CheckSetCollision(associatedAST, set, a, b); set.Add(a, b); } } else if (t.Type == ANTLRParser.LEXER_CHAR_SET) { set.AddAll(GetSetFromCharSetLiteral(t)); } else if (t.Type == ANTLRParser.STRING_LITERAL) { int c = CharSupport.GetCharValueFromGrammarCharLiteral(t.Text); if (c != -1) { CheckSetCollision(associatedAST, set, c); set.Add(c); } else { g.tool.errMgr.GrammarError(ErrorType.INVALID_LITERAL_IN_LEXER_SET, g.fileName, t.Token, t.Text); } } else if (t.Type == ANTLRParser.TOKEN_REF) { g.tool.errMgr.GrammarError(ErrorType.UNSUPPORTED_REFERENCE_IN_LEXER_SET, g.fileName, t.Token, t.Text); } } if (invert) { left.AddTransition(new NotSetTransition(right, set)); } else { Transition transition; if (set.GetIntervals().Count == 1) { Interval interval = set.GetIntervals()[0]; transition = new RangeTransition(right, interval.a, interval.b); } else { transition = new SetTransition(right, set); } left.AddTransition(transition); } associatedAST.atnState = left; return new Handle(left, right); }
private static void OptimizeSets(Grammar g, ATN atn) { if (g.IsParser()) { // parser codegen doesn't currently support SetTransition return; } int removedStates = 0; IList<DecisionState> decisions = atn.decisionToState; foreach (DecisionState decision in decisions) { if (decision.ruleIndex >= 0) { Rule rule = g.GetRule(decision.ruleIndex); if (char.IsLower(rule.name[0])) { // parser codegen doesn't currently support SetTransition continue; } } IntervalSet setTransitions = new IntervalSet(); for (int i = 0; i < decision.NumberOfTransitions; i++) { Transition epsTransition = decision.Transition(i); if (!(epsTransition is EpsilonTransition)) { continue; } if (epsTransition.target.NumberOfTransitions != 1) { continue; } Transition transition = epsTransition.target.Transition(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); } } // due to min alt resolution policies, can only collapse sequential alts for (int i = setTransitions.GetIntervals().Count - 1; i >= 0; i--) { Interval interval = setTransitions.GetIntervals()[i]; if (interval.Length <= 1) { continue; } ATNState blockEndState = decision.Transition(interval.a).target.Transition(0).target; IntervalSet matchSet = new IntervalSet(); for (int j = interval.a; j <= interval.b; j++) { Transition matchTransition = decision.Transition(j).target.Transition(0); if (matchTransition is NotSetTransition) { throw new NotImplementedException(); } IntervalSet set = matchTransition.Label; int minElem = set.MinElement; int maxElem = set.MaxElement; for (int k = minElem; k <= maxElem; k++) { if (matchSet.Contains(k)) { char setMin = (char)set.MinElement; char setMax = (char)set.MaxElement; // TODO: Token is missing (i.e. position in source will not be displayed). g.tool.errMgr.GrammarError(ErrorType.CHARACTERS_COLLISION_IN_SET, g.fileName, null, (char)minElem + "-" + (char)maxElem, "[" + setMin + "-" + setMax + "]"); break; } } matchSet.AddAll(set); } 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); } decision.Transition(interval.a).target.SetTransition(0, newTransition); for (int j = interval.a + 1; j <= interval.b; j++) { Transition removed = decision.Transition(interval.a + 1); decision.RemoveTransition(interval.a + 1); atn.RemoveState(removed.target); removedStates++; } } } //System.Console.WriteLine("ATN optimizer removed " + removedStates + " states by collapsing sets."); }