Пример #1
0
 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);
                 }
             }
         }
     }
 }
Пример #2
0
        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));
        }
Пример #3
0
        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.");
        }