Exemple #1
0
        public IntervalSet GetFollowSet(PreventContextType preventContextType)
        {
            if (_followSet != null && _followSet[(int)preventContextType] != null)
            {
                return(_followSet[(int)preventContextType]);
            }

            IntervalSet[] sets     = _followSet ?? new IntervalSet[Enum.GetValues(typeof(PreventContextType)).Cast <int>().Max() + 1];
            IntervalSet   set      = new IntervalSet();
            var           queue    = new Queue <Tuple <Transition, PreventContextType> >(OutgoingTransitions.Select(i => Tuple.Create(i, preventContextType)));
            var           comparer = new TupleEqualityComparer <Transition, PreventContextType>(ObjectReferenceEqualityComparer <Transition> .Default, null);
            var           visited  = new HashSet <Tuple <Transition, PreventContextType> >(queue, comparer);

            while (queue.Count > 0)
            {
                var                pair                   = queue.Dequeue();
                Transition         transition             = pair.Item1;
                PreventContextType nextPreventContextType = pair.Item2;

                if (transition.IsContext)
                {
                    switch (nextPreventContextType)
                    {
                    case PreventContextType.Pop:
                        if (!transition.IsRecursive && transition is PopContextTransition)
                        {
                            continue;
                        }

                        break;

                    case PreventContextType.PopRecursive:
                        if (transition.IsRecursive && (transition is PopContextTransition))
                        {
                            continue;
                        }

                        break;

                    case PreventContextType.Push:
                        if (!transition.IsRecursive && transition is PushContextTransition)
                        {
                            continue;
                        }

                        break;

                    case PreventContextType.PushRecursive:
                        if (transition.IsRecursive && (transition is PushContextTransition))
                        {
                            continue;
                        }

                        break;

                    default:
                        break;
                    }
                }

                if (transition.IsEpsilon || transition.IsContext)
                {
                    // the preventContextType can only change if we're following a another context transition
                    if (transition.IsContext)
                    {
                        nextPreventContextType = PreventContextType.None;
                        if (transition.SourceState.IsOptimized)
                        {
                            if (transition is PushContextTransition)
                            {
                                nextPreventContextType = transition.IsRecursive ? PreventContextType.PushRecursive : PreventContextType.Push;
                            }
                            else if (transition is PopContextTransition)
                            {
                                nextPreventContextType = transition.IsRecursive ? PreventContextType.PopRecursive : PreventContextType.Pop;
                            }
                        }
                    }

                    if (transition.TargetState._followSet != null && transition.TargetState._followSet[(int)nextPreventContextType] != null)
                    {
                        set.UnionWith(transition.TargetState._followSet[(int)nextPreventContextType]);
                    }
                    else
                    {
                        foreach (var outgoing in transition.TargetState.OutgoingTransitions)
                        {
                            var nextPair = Tuple.Create(outgoing, nextPreventContextType);
                            if (visited.Add(nextPair))
                            {
                                queue.Enqueue(Tuple.Create(outgoing, nextPreventContextType));
                            }
                        }
                    }
                }
                else
                {
                    set.UnionWith(transition.MatchSet);
                }
            }

            _followSet = sets;
            _followSet[(int)preventContextType] = set;

            return(set);
        }
Exemple #2
0
        private void AddOptimizedTransitions(StateOptimizer optimizer, HashSet <Transition> visited, Transition transition, PreventContextType preventContextType)
        {
            Contract.Requires(optimizer != null);
            Contract.Requires(visited != null);
            Contract.Requires(transition != null);
            Contract.Requires(transition.SourceState == null);
            Contract.Requires(preventContextType != PreventContextType.PushRecursive && preventContextType != PreventContextType.PopRecursive);

            Contract.Ensures(visited.Count == Contract.OldValue(visited.Count));

            List <Transition> addedTransitions = null;

            if (transition.TargetState == this)
            {
                return;
            }

            try
            {
                while (true)
                {
                    /* Done when we find:
                     *  - a match transition
                     *  - a recursive transition (which should already be analyzed)
                     */

                    if (transition.IsMatch || transition.TargetState.OutgoingTransitions.Count == 0 || transition.IsRecursive)
                    {
                        //if (!transition.IsMatch && transition.TargetState.OutgoingTransitions.Count > 0)
                        //{
                        //    // must be here because it's a recursive state
                        //    transition.IsRecursive = true;
                        //}

                        AddTransitionInternal(transition, optimizer);
                        return;
                    }

                    // inline merge of single epsilon transitions
                    if (transition.TargetState.OutgoingTransitions.Count == 1 && transition.TargetState.OutgoingTransitions.First().IsEpsilon)
                    {
                        if (!visited.Add(transition.TargetState.OutgoingTransitions.First()))
                        {
                            throw new InvalidOperationException();
                        }

                        addedTransitions = addedTransitions ?? new List <Transition>();
                        addedTransitions.Add(transition.TargetState.OutgoingTransitions.First());
                        transition = MergeTransitions(transition, transition.TargetState.OutgoingTransitions.First());
                        continue;
                    }

                    break;
                }

                bool added = false;

                foreach (var nextTransition in transition.TargetState.OutgoingTransitions.ToArray())
                {
                    bool preventMerge = nextTransition.IsRecursive;

                    if (!nextTransition.IsRecursive)
                    {
                        switch (preventContextType)
                        {
                        case PreventContextType.Pop:
                            if (transition is PopContextTransition)
                            {
                                preventMerge = true;
                            }

                            break;

                        case PreventContextType.Push:
                            if (transition is PushContextTransition)
                            {
                                preventMerge = true;
                            }

                            break;

                        default:
                            break;
                        }
                    }

                    if (transition.IsEpsilon)
                    {
                        if (preventMerge && !added)
                        {
                            AddTransitionInternal(transition, optimizer);
                            added = true;
                            continue;
                        }

                        if (!visited.Add(nextTransition))
                        {
                            continue;
                        }

                        try
                        {
                            Contract.Assert(!preventMerge);
                            AddOptimizedTransitions(optimizer, visited, MergeTransitions(transition, nextTransition), preventContextType);
                        }
                        finally
                        {
                            visited.Remove(nextTransition);
                        }
                    }
                    else if (transition.IsContext)
                    {
                        PreventContextType nextPreventContextType = PreventContextType.None;
                        if (!preventMerge && transition.TargetState.IsOptimized)
                        {
                            if (nextTransition is PushContextTransition)
                            {
                                nextPreventContextType = PreventContextType.Push;
                            }
                            else if (nextTransition is PopContextTransition)
                            {
                                nextPreventContextType = PreventContextType.Pop;
                            }
                        }

                        bool canMerge = !preventMerge && !nextTransition.IsMatch;

                        if (canMerge && nextTransition.IsContext)
                        {
                            canMerge = (transition is PopContextTransition && nextTransition is PopContextTransition) ||
                                       (transition is PushContextTransition && nextTransition is PushContextTransition);

#if false
                            if (canMerge)
                            {
                                bool recursive = ((ContextTransition)transition).ContextIdentifiers.Any(((ContextTransition)nextTransition).ContextIdentifiers.Contains);
                                if (recursive)
                                {
                                    transition.IsRecursive = true;
                                    canMerge = false;
                                }
                            }
#endif
                        }

                        if (canMerge)
                        {
                            if (!visited.Add(nextTransition))
                            {
                                continue;
                            }

                            try
                            {
                                AddOptimizedTransitions(optimizer, visited, MergeTransitions(transition, nextTransition), nextPreventContextType);
                            }
                            finally
                            {
                                visited.Remove(nextTransition);
                            }
                        }
                        else if (!added)
                        {
                            AddTransitionInternal(transition, optimizer);
                            added = true;
                        }
                    }
                }
            }
            finally
            {
                if (addedTransitions != null)
                {
                    visited.ExceptWith(addedTransitions);
                }
            }
        }