internal void RemoveTransition(Transition transition)
        {
            Contract.Requires<ArgumentNullException>(transition != null, "transition");

            RemoveReachableTransition(transition);

            PushContextTransition pushContextTransition = transition as PushContextTransition;
            if (pushContextTransition != null)
            {
                int context = pushContextTransition.ContextIdentifiers[0];
                HashSet<PushContextTransition> transitions = _pushContextTransitions[context];
                transitions.Remove(pushContextTransition);
            }

            PopContextTransition popContextTransition = transition as PopContextTransition;
            if (popContextTransition != null)
            {
                int context = popContextTransition.ContextIdentifiers.Last();
                HashSet<PopContextTransition> transitions = _popContextTransitions[context];
                transitions.Remove(popContextTransition);
            }
        }
        private void RemoveReachableTransition(Transition transition)
        {
            Contract.Requires(transition != null);

            if (!_reachableTransitions.Remove(transition))
                throw new InvalidOperationException();
        }
        internal void AddTransition(Transition transition)
        {
            Contract.Requires<ArgumentNullException>(transition != null, "transition");

            AddReachableTransition(transition);

            PushContextTransition pushContextTransition = transition as PushContextTransition;
            if (pushContextTransition != null)
            {
                int context = pushContextTransition.ContextIdentifiers[0];
                HashSet<PushContextTransition> transitions;
                if (!_pushContextTransitions.TryGetValue(context, out transitions))
                {
                    transitions = new HashSet<PushContextTransition>(ObjectReferenceEqualityComparer<Transition>.Default);
                    _pushContextTransitions[context] = transitions;
                }

                transitions.Add(pushContextTransition);
            }

            PopContextTransition popContextTransition = transition as PopContextTransition;
            if (popContextTransition != null)
            {
                int context = popContextTransition.ContextIdentifiers.Last();
                HashSet<PopContextTransition> transitions;
                if (!_popContextTransitions.TryGetValue(context, out transitions))
                {
                    transitions = new HashSet<PopContextTransition>(ObjectReferenceEqualityComparer<Transition>.Default);
                    _popContextTransitions[context] = transitions;
                }

                transitions.Add(popContextTransition);
            }
        }
        private static string GetTransitionLabel(Transition transition, IList<string> tokenNames)
        {
            if (transition.IsEpsilon)
                return string.Empty;

            ContextTransition contextTransition = transition as ContextTransition;
            if (contextTransition != null)
            {
                string type = transition is PushContextTransition ? "push" : "pop";
                string context = string.Join(" ", contextTransition.ContextIdentifiers);

                //string sourceSet = transition.SourceState.IsOptimized ? transition.SourceState.GetSourceSet(preventContextType) : transition.SourceState.GetSourceSet();

                return string.Format("{0} {1}", type, context);
            }

            return transition.MatchSet.ToString(tokenNames);
        }