protected virtual void GetRuleStates(StateOptimizer optimizer, RuleBinding ruleName, State state, Dictionary <int, RuleBinding> stateRules) { if (stateRules.ContainsKey(state.Id)) { return; } stateRules[state.Id] = ruleName; foreach (var transition in state.OutgoingTransitions) { if (transition is PopContextTransition) { continue; } PushContextTransition contextTransition = transition as PushContextTransition; if (contextTransition != null) { foreach (var popTransition in optimizer.GetPopContextTransitions(contextTransition)) { GetRuleStates(optimizer, ruleName, popTransition.TargetState, stateRules); } } else { GetRuleStates(optimizer, ruleName, transition.TargetState, stateRules); } } }
private void GetSiblingStates(State currentState, HashSet <State> states) { foreach (var transition in currentState.OutgoingTransitions) { if (transition.IsContext) { PushContextTransition pushContextTransition = transition as PushContextTransition; if (pushContextTransition == null) { continue; } foreach (var popTransition in Optimizer.GetPopContextTransitions(pushContextTransition)) { if (states.Add(popTransition.TargetState)) { GetSiblingStates(popTransition.TargetState, states); } } } else if (states.Add(transition.TargetState)) { GetSiblingStates(transition.TargetState, states); } } }
private bool AddRecursivePushTransitions([NotNull] HashSet <State> visited, [NotNull] State currentState, Transition effectiveTransition, [NotNull] List <int> contexts, StateOptimizer optimizer) { Debug.Assert(visited != null); Debug.Assert(currentState != null); Debug.Assert(contexts != null); bool foundRecursive = false; foreach (var transition in currentState.OutgoingTransitions.Where(i => !i.IsRecursive && (i.IsEpsilon || (i is PushContextTransition))).ToArray()) { ContextTransition contextTransition = transition as ContextTransition; try { if (contextTransition != null) { contexts.AddRange(contextTransition.ContextIdentifiers); } if (transition.TargetState == this) { foundRecursive = true; if (contexts.Count == 0) { Trace.WriteLine(string.Format("State {0} is self-recursive.", this.Id)); continue; } PushContextTransition recursive = new PushContextTransition(this, contexts); recursive.IsRecursive = true; AddTransitionInternal(recursive, optimizer); continue; } if (!visited.Add(transition.TargetState)) { continue; } try { AddRecursivePushTransitions(visited, transition.TargetState, MergeTransitions(effectiveTransition, transition), contexts, optimizer); } finally { visited.Remove(transition.TargetState); } } finally { if (contextTransition != null) { contexts.RemoveRange(contexts.Count - contextTransition.ContextIdentifiers.Count, contextTransition.ContextIdentifiers.Count); } } } return(foundRecursive); }
private IEnumerable <State> GetEnclosedStates(PushContextTransition transition) { HashSet <State> states = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default); states.Add(transition.TargetState); GetSiblingStates(transition.TargetState, states); return(states); }
public static Nfa Rule(RuleBinding ruleBinding) { State startState = new State(); State endState = new State(); PushContextTransition push = new PushContextTransition(ruleBinding.StartState, startState.Id); PopContextTransition pop = new PopContextTransition(endState, startState.Id); startState.AddTransition(push); ruleBinding.EndState.AddTransition(pop); return(new Nfa(startState, endState)); }
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); } }
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); } }
internal void RemoveTransition([NotNull] Transition transition) { Requires.NotNull(transition, nameof(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 IEnumerable<State> GetEnclosedStates(PushContextTransition transition) { HashSet<State> states = new HashSet<State>(ObjectReferenceEqualityComparer<State>.Default); states.Add(transition.TargetState); GetSiblingStates(transition.TargetState, states); return states; }
private Transition MergeTransitions(Transition first, Transition second) { Contract.Requires(first != null); Contract.Requires(second != null); Contract.Ensures(Contract.Result <Transition>().SourceState == null); Contract.Ensures(Contract.Result <Transition>().IsRecursive == second.IsRecursive); Contract.Assert(!first.IsRecursive); Contract.Assert(first.IsEpsilon || !second.IsRecursive); if (first.IsMatch) { if (!second.IsEpsilon) { throw new InvalidOperationException(); } MatchRangeTransition matchRangeTransition = first as MatchRangeTransition; if (matchRangeTransition != null) { return(new MatchRangeTransition(second.TargetState, matchRangeTransition.Range)); } throw new NotImplementedException("Unknown match transition type."); } if (first.IsEpsilon) { if (second.IsEpsilon) { return(new EpsilonTransition(second.TargetState)); } MatchRangeTransition matchRangeTransition = second as MatchRangeTransition; if (matchRangeTransition != null) { return(new MatchRangeTransition(second.TargetState, matchRangeTransition.Range)); } PopContextTransition popContextTransition = second as PopContextTransition; if (popContextTransition != null) { var transition = new PopContextTransition(second.TargetState, popContextTransition.ContextIdentifiers); //transition.PushTransitions.UnionWith(popContextTransition.PushTransitions); //Contract.Assert(Contract.ForAll(transition.PushTransitions, i => i.SourceState != null)); return(transition); } PushContextTransition pushContextTransition = second as PushContextTransition; if (pushContextTransition != null) { var transition = new PushContextTransition(second.TargetState, pushContextTransition.ContextIdentifiers); //transition.PopTransitions.UnionWith(pushContextTransition.PopTransitions); //Contract.Assert(Contract.ForAll(transition.PopTransitions, i => i.SourceState != null)); return(transition); } throw new NotSupportedException(); } PopContextTransition popFirst = first as PopContextTransition; if (popFirst != null) { if (second.IsEpsilon) { var transition = new PopContextTransition(second.TargetState, popFirst.ContextIdentifiers); //transition.PushTransitions.UnionWith(popFirst.PushTransitions); //Contract.Assert(Contract.ForAll(transition.PushTransitions, i => i.SourceState != null)); return(transition); } PopContextTransition popSecond = second as PopContextTransition; if (popSecond != null) { var transition = new PopContextTransition(popSecond.TargetState, popFirst.ContextIdentifiers.Concat(popSecond.ContextIdentifiers)); ////transition.PushTransitions.UnionWith(popFirst.PushTransitions); //transition.PushTransitions.UnionWith(popSecond.PushTransitions); //Contract.Assert(Contract.ForAll(transition.PushTransitions, i => i.SourceState != null)); return(transition); } if (second is PushContextTransition) { throw new InvalidOperationException(); } if (second.IsMatch) { throw new NotSupportedException(); } throw new NotImplementedException(); } PushContextTransition pushFirst = first as PushContextTransition; if (pushFirst != null) { if (second.IsEpsilon) { var transition = new PushContextTransition(second.TargetState, pushFirst.ContextIdentifiers); //transition.PopTransitions.UnionWith(pushFirst.PopTransitions); //Contract.Assert(Contract.ForAll(transition.PopTransitions, i => i.SourceState != null)); return(transition); } PushContextTransition pushSecond = second as PushContextTransition; if (pushSecond != null) { var transition = new PushContextTransition(pushSecond.TargetState, pushFirst.ContextIdentifiers.Concat(pushSecond.ContextIdentifiers)); //transition.PopTransitions.UnionWith(pushFirst.PopTransitions); ////transition.PopTransitions.UnionWith(pushSecond.PopTransitions); //Contract.Assert(Contract.ForAll(transition.PopTransitions, i => i.SourceState != null)); return(transition); } if (second is PopContextTransition) { throw new InvalidOperationException(); } if (second.IsMatch) { throw new NotSupportedException(); } throw new NotImplementedException(); } throw new NotImplementedException(); }
internal void AddTransitionInternal(Transition transition, StateOptimizer optimizer) { Contract.Requires(transition != null); Contract.Requires(transition.SourceState == null); #if ALL_CHECKS Contract.Requires(!OutgoingTransitions.Contains(transition)); Contract.Requires(!transition.TargetState.IncomingTransitions.Contains(transition)); #endif if (IsRecursiveAnalysisComplete && !transition.IsMatch && transition.TargetState == this && !transition.IsRecursive) { throw new InvalidOperationException(); } PopContextTransition popContextTransition = transition as PopContextTransition; PushContextTransition pushContextTransition = transition as PushContextTransition; #if false if (popContextTransition != null && !transition.IsRecursive) { foreach (var recursive in OutgoingTransitions.OfType <PopContextTransition>().Where(i => i.IsRecursive)) { if (popContextTransition.ContextIdentifiers.Take(recursive.ContextIdentifiers.Count).SequenceEqual(recursive.ContextIdentifiers)) { if (popContextTransition.ContextIdentifiers.Count > recursive.ContextIdentifiers.Count) { throw new InvalidOperationException(); } } } } #endif if (_outgoingTransitions.Count > 10 && !(_outgoingTransitions is ISet <Transition>)) { _outgoingTransitions = new HashSet <Transition>(_outgoingTransitions, ObjectReferenceEqualityComparer <Transition> .Default); } #if false if (transition.IsContext && transition.IsRecursive) { PopContextTransition first = transition as PopContextTransition; if (first != null) { foreach (var existing in OutgoingTransitions.OfType <PopContextTransition>().ToArray()) { if (existing.TargetState != transition.TargetState) { continue; } if (first.ContextIdentifiers.Take(existing.ContextIdentifiers.Count).SequenceEqual(existing.ContextIdentifiers)) { RemoveTransitionInternal(existing, optimizer); } } } PushContextTransition second = transition as PushContextTransition; if (second != null) { foreach (var existing in OutgoingTransitions.OfType <PushContextTransition>().ToArray()) { if (existing.TargetState != transition.TargetState) { continue; } if (second.ContextIdentifiers.Take(existing.ContextIdentifiers.Count).SequenceEqual(existing.ContextIdentifiers)) { RemoveTransitionInternal(existing, optimizer); } } } } #endif OutgoingTransitions.Add(transition); if (transition.TargetState.IncomingTransitions.Count > 10 && !(transition.TargetState.IncomingTransitions is ISet <Transition>)) { transition.TargetState._incomingTransitions = new HashSet <Transition>(transition.TargetState._incomingTransitions, ObjectReferenceEqualityComparer <Transition> .Default); } transition.TargetState.IncomingTransitions.Add(transition); transition.SourceState = this; if (optimizer != null) { optimizer.AddTransition(transition); } if (popContextTransition != null) { //if (optimizer != null) // popContextTransition.PushTransitions.UnionWith(optimizer.GetPushContextTransitions(popContextTransition.ContextIdentifiers.Last())); //foreach (var pushTransition in popContextTransition.PushTransitions) //{ // Contract.Assert(pushTransition.ContextIdentifiers.First() == popContextTransition.ContextIdentifiers.Last()); // Contract.Assert(pushTransition.SourceState != null); // pushTransition.PopTransitions.Add(popContextTransition); //} #if ALL_CHECKS Contract.Assert(Contract.ForAll(OutgoingTransitions.OfType <PushContextTransition>(), i => i.ContextIdentifiers.Last() != popContextTransition.ContextIdentifiers.First() || popContextTransition.PushTransitions.Contains(i))); #endif } else if (pushContextTransition != null) { //if (optimizer != null) // pushContextTransition.PopTransitions.UnionWith(optimizer.GetPopContextTransitions(pushContextTransition.ContextIdentifiers[0])); //foreach (var popTransition in pushContextTransition.PopTransitions) //{ // Contract.Assert(popTransition.ContextIdentifiers.Last() == pushContextTransition.ContextIdentifiers.First()); // Contract.Assert(popTransition.SourceState != null); // popTransition.PushTransitions.Add(pushContextTransition); //} #if ALL_CHECKS Contract.Assert(Contract.ForAll(OutgoingTransitions.OfType <PopContextTransition>(), i => i.ContextIdentifiers.Last() != pushContextTransition.ContextIdentifiers.First() || pushContextTransition.PopTransitions.Contains(i))); #endif } _followSet = null; _isForwardRecursive = null; transition.TargetState._sourceSet = null; transition.TargetState._isBackwardRecursive = null; }
public static Nfa Rule(RuleBinding ruleBinding) { State startState = new State(); State endState = new State(); PushContextTransition push = new PushContextTransition(ruleBinding.StartState, startState.Id); PopContextTransition pop = new PopContextTransition(endState, startState.Id); startState.AddTransition(push); ruleBinding.EndState.AddTransition(pop); return new Nfa(startState, endState); }
internal IEnumerable <PopContextTransition> GetPopContextTransitions(PushContextTransition pushContextTransition) { Contract.Requires <ArgumentNullException>(pushContextTransition != null, "pushContextTransition"); Contract.Ensures(Contract.Result <IEnumerable <PopContextTransition> >() != null); return(GetPopContextTransitions(pushContextTransition.ContextIdentifiers[0])); }
internal IEnumerable<PopContextTransition> GetPopContextTransitions(PushContextTransition pushContextTransition) { Contract.Requires<ArgumentNullException>(pushContextTransition != null, "pushContextTransition"); Contract.Ensures(Contract.Result<IEnumerable<PopContextTransition>>() != null); return GetPopContextTransitions(pushContextTransition.ContextIdentifiers[0]); }
internal IEnumerable <PopContextTransition> GetPopContextTransitions([NotNull] PushContextTransition pushContextTransition) { Requires.NotNull(pushContextTransition, nameof(pushContextTransition)); return(GetPopContextTransitions(pushContextTransition.ContextIdentifiers[0])); }