public override void VisitState([NotNull] ATNState p) { if (p.StateType == StateType.Basic && p.NumberOfTransitions == 1) { ATNState q = p.Transition(0).target; if (p.Transition(0) is RuleTransition) { q = ((RuleTransition)p.Transition(0)).followState; } if (q.StateType == StateType.Basic) { // we have p-x->q for x in {rule, action, pred, token, ...} // if edge out of q is single epsilon to block end // we can strip epsilon p-x->q-eps->r Transition trans = q.Transition(0); if (q.NumberOfTransitions == 1 && trans is EpsilonTransition) { ATNState r = trans.target; if (r is BlockEndState || r is PlusLoopbackState || r is StarLoopbackState) { // skip over q if (p.Transition(0) is RuleTransition) { ((RuleTransition)p.Transition(0)).followState = r; } else { p.Transition(0).target = r; } _atn.RemoveState(q); } } } } }
public virtual Handle ElemList([NotNull] IList <Handle> els) { int n = els.Count; for (int i = 0; i < n - 1; i++) // hook up elements (visit all but last) { Handle el = els[i]; // if el is of form o-x->o for x in {rule, action, pred, token, ...} // and not last in alt Transition tr = null; if (el.left.NumberOfTransitions == 1) { tr = el.left.Transition(0); } bool isRuleTrans = tr is RuleTransition; if (el.left.StateType == StateType.Basic && el.right.StateType == StateType.Basic && tr != null && (isRuleTrans && ((RuleTransition)tr).followState == el.right || tr.target == el.right)) { // we can avoid epsilon edge to next el if (isRuleTrans) { ((RuleTransition)tr).followState = els[i + 1].left; } else { tr.target = els[i + 1].left; } atn.RemoveState(el.right); // we skipped over this state } else // need epsilon if previous block's right end node is complicated { Epsilon(el.right, els[i + 1].left); } } Handle first = els[0]; Handle last = els[n - 1]; if (first == null || last == null) { g.tool.errMgr.ToolError(ErrorType.INTERNAL_ERROR, "element list has first|last == null"); } return(new Handle(first.left, last.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."); }