public Network(NetworkBuilder builder, StateOptimizer optimizer, IEnumerable <RuleBinding> rules, Dictionary <int, RuleBinding> stateRules, Dictionary <int, RuleBinding> contextRules) { Contract.Requires <ArgumentNullException>(builder != null, "builder"); Contract.Requires <ArgumentNullException>(optimizer != null, "optimizer"); Contract.Requires <ArgumentNullException>(rules != null, "rules"); _builder = builder; _rules = new List <RuleBinding>(rules); //Dictionary<int, string> stateRules = new Dictionary<int, string>(); //foreach (var rule in _rules) //{ // stateRules[rule.StartState.Id] = rule.Name; // stateRules[rule.EndState.Id] = rule.Name; //} HashSet <State> states = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default); HashSet <Transition> transitions = new HashSet <Transition>(ObjectReferenceEqualityComparer <Transition> .Default); foreach (var rule in _rules) { ExtractStatesAndTransitions(optimizer, rule, rule.StartState, states, transitions, stateRules, contextRules); //ExtractStatesAndTransitions(rule.Name, rule.EndState, states, transitions, stateRules, contextRules); } _states = states.ToDictionary(i => i.Id); _transitions = new List <Transition>(transitions); _stateRules = stateRules; _contextRules = contextRules; _optimizer = optimizer; }
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); } } }
public Network([NotNull] NetworkBuilder builder, [NotNull] StateOptimizer optimizer, [NotNull] IEnumerable <RuleBinding> rules, Dictionary <int, RuleBinding> stateRules, Dictionary <int, RuleBinding> contextRules) { Requires.NotNull(builder, nameof(builder)); Requires.NotNull(optimizer, nameof(optimizer)); Requires.NotNull(rules, nameof(rules)); _builder = builder; _rules = new List <RuleBinding>(rules); //Dictionary<int, string> stateRules = new Dictionary<int, string>(); //foreach (var rule in _rules) //{ // stateRules[rule.StartState.Id] = rule.Name; // stateRules[rule.EndState.Id] = rule.Name; //} HashSet <State> states = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default); HashSet <Transition> transitions = new HashSet <Transition>(ObjectReferenceEqualityComparer <Transition> .Default); foreach (var rule in _rules) { ExtractStatesAndTransitions(optimizer, rule, rule.StartState, states, transitions, stateRules, contextRules); //ExtractStatesAndTransitions(rule.Name, rule.EndState, states, transitions, stateRules, contextRules); } _states = states.ToDictionary(i => i.Id); _transitions = new List <Transition>(transitions); _stateRules = stateRules; _contextRules = contextRules; _optimizer = optimizer; }
public Network(NetworkBuilder builder, StateOptimizer optimizer, IEnumerable<RuleBinding> rules, Dictionary<int, RuleBinding> stateRules, Dictionary<int, RuleBinding> contextRules) { Contract.Requires<ArgumentNullException>(builder != null, "builder"); Contract.Requires<ArgumentNullException>(optimizer != null, "optimizer"); Contract.Requires<ArgumentNullException>(rules != null, "rules"); _builder = builder; _rules = new List<RuleBinding>(rules); //Dictionary<int, string> stateRules = new Dictionary<int, string>(); //foreach (var rule in _rules) //{ // stateRules[rule.StartState.Id] = rule.Name; // stateRules[rule.EndState.Id] = rule.Name; //} HashSet<State> states = new HashSet<State>(ObjectReferenceEqualityComparer<State>.Default); HashSet<Transition> transitions = new HashSet<Transition>(ObjectReferenceEqualityComparer<Transition>.Default); foreach (var rule in _rules) { ExtractStatesAndTransitions(optimizer, rule, rule.StartState, states, transitions, stateRules, contextRules); //ExtractStatesAndTransitions(rule.Name, rule.EndState, states, transitions, stateRules, contextRules); } _states = states.ToDictionary(i => i.Id); _transitions = new List<Transition>(transitions); _stateRules = stateRules; _contextRules = contextRules; _optimizer = optimizer; }
public void RemoveTransition(Transition transition, StateOptimizer optimizer = null) { Requires.NotNull(transition, nameof(transition)); Requires.Argument(transition.SourceState == this, nameof(transition), "The transition source state must be the current instance."); Verify.Operation(OutgoingTransitions.Contains(transition), "Expected the state to contain the transition."); RemoveTransitionInternal(transition, optimizer); }
public void AddTransition(Transition transition, StateOptimizer optimizer = null) { Contract.Requires <ArgumentNullException>(transition != null, "transition"); Contract.Requires <InvalidOperationException>(transition.SourceState == null); Contract.Requires <InvalidOperationException>(!OutgoingTransitions.Contains(transition)); Contract.Requires <InvalidOperationException>(!transition.TargetState.IncomingTransitions.Contains(transition)); AddTransitionInternal(transition, optimizer); }
public void AddTransition(Transition transition, StateOptimizer optimizer = null) { Requires.NotNull(transition, nameof(transition)); Verify.Operation(transition.SourceState == null, "Expected the transition to not be associated with a source state."); Verify.Operation(!OutgoingTransitions.Contains(transition), "Expected the state to not already contain the transition."); Verify.Operation(!transition.TargetState.IncomingTransitions.Contains(transition), "Expected the target state to not already contain the incoming transition."); AddTransitionInternal(transition, optimizer); }
public void RemoveTransition(Transition transition, StateOptimizer optimizer = null) { Contract.Requires <ArgumentNullException>(transition != null, "transition"); Contract.Requires <ArgumentException>(transition.SourceState == this); Contract.Requires <InvalidOperationException>(OutgoingTransitions.Contains(transition)); Contract.Ensures(transition.SourceState == null); Contract.Ensures(!Contract.OldValue(transition.SourceState).OutgoingTransitions.Contains(transition)); Contract.Ensures(!transition.TargetState.IncomingTransitions.Contains(transition)); RemoveTransitionInternal(transition, optimizer); }
public void Optimize([NotNull] StateOptimizer optimizer) { Requires.NotNull(optimizer, nameof(optimizer)); Verify.Operation(IsRecursiveAnalysisComplete, "Expected recursive analysis to be complete."); if (IsOptimized) { return; } OptimizeOutgoingTransitions(optimizer); _isOptimized = true; }
public void Optimize(StateOptimizer optimizer) { Contract.Requires <ArgumentNullException>(optimizer != null, "optimizer"); Contract.Requires <InvalidOperationException>(IsRecursiveAnalysisComplete); if (IsOptimized) { return; } OptimizeOutgoingTransitions(optimizer); _isOptimized = true; }
internal void RemoveTransitionInternal(Transition transition, StateOptimizer optimizer) { Contract.Requires(transition != null, "transition"); Contract.Requires(transition.SourceState == this); #if ALL_CHECKS Contract.Requires(OutgoingTransitions.Contains(transition)); #endif Contract.Ensures(transition.SourceState == null); #if ALL_CHECKS Contract.Ensures(!Contract.OldValue(transition.SourceState).OutgoingTransitions.Contains(transition)); Contract.Ensures(!transition.TargetState.IncomingTransitions.Contains(transition)); Contract.Assert(transition.TargetState.IncomingTransitions.Contains(transition)); #endif //PopContextTransition popContextTransition = transition as PopContextTransition; //if (popContextTransition != null) //{ // foreach (var pushTransition in popContextTransition.PushTransitions) // { // Contract.Assert(pushTransition.PopTransitions.Contains(transition)); // pushTransition.PopTransitions.Remove(popContextTransition); // } //} //PushContextTransition pushContextTransition = transition as PushContextTransition; //if (pushContextTransition != null) //{ // foreach (var popTransition in pushContextTransition.PopTransitions) // { // Contract.Assert(popTransition.PushTransitions.Contains(transition)); // popTransition.PushTransitions.Remove(pushContextTransition); // } //} if (optimizer != null) { optimizer.RemoveTransition(transition); } OutgoingTransitions.Remove(transition); transition.TargetState.IncomingTransitions.Remove(transition); _followSet = null; _isForwardRecursive = null; transition.TargetState._sourceSet = null; transition.TargetState._isBackwardRecursive = null; transition.SourceState = null; }
public void AddRecursiveTransitions(StateOptimizer optimizer) { if (_recursiveTransitions != null) { return; } int originalTransitionCount = OutgoingTransitions.Count; HashSet <State> visited = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default); List <int> trace = new List <int>(); AddRecursivePushTransitions(visited, this, new EpsilonTransition(this), trace, optimizer); AddRecursivePopTransitions(visited, this, new EpsilonTransition(this), trace, optimizer); _recursiveTransitions = OutgoingTransitions.Count != originalTransitionCount; }
protected virtual int RemoveUnreachableStates(StateOptimizer optimizer, IEnumerable <RuleBinding> rules, HashSet <State> states, HashSet <State> ruleStartStates) { int removedCount = 0; while (true) { HashSet <State> reachableStates = GetReachableStates(rules); bool removed = false; foreach (var state in states) { // already removed (or a terminal state) if (state.OutgoingTransitions.Count == 0) { continue; } /* if there are no incoming transitions and it's not a rule start state, * then the state is unreachable so we remove it. */ if (!reachableStates.Contains(state)) { removedCount++; removed = true; foreach (var transition in state.OutgoingTransitions.ToArray()) { state.RemoveTransition(transition, optimizer); } } } if (!removed) { break; } } #if DEBUG int recursiveStates = GetReachableStates(rules).Count(i => i.HasRecursiveTransitions ?? true); #endif return(removedCount); }
private void OptimizeOutgoingTransitions(StateOptimizer optimizer) { List <Transition> oldTransitions = new List <Transition>(OutgoingTransitions.Where(i => !i.IsRecursive)); foreach (var transition in oldTransitions) { RemoveTransitionInternal(transition, optimizer); } Contract.Assert(Contract.ForAll(OutgoingTransitions, i => i.IsRecursive)); foreach (var transition in oldTransitions) { HashSet <Transition> visited = new HashSet <Transition>(ObjectReferenceEqualityComparer <Transition> .Default); visited.Add(transition); AddOptimizedTransitions(optimizer, visited, transition, PreventContextType.None); } Contract.Assert(oldTransitions.Count == 0 || OutgoingTransitions.Count > 0); }
public void RemoveExtraEpsilonTransitions(StateOptimizer optimizer, bool isStartState) { if (OutgoingTransitions.Count == 1 && OutgoingTransitions.First().IsEpsilon) { Transition epsilon = OutgoingTransitions.First(); foreach (var incoming in IncomingTransitions.ToArray()) { State sourceState = incoming.SourceState; sourceState.RemoveTransitionInternal(incoming, optimizer); sourceState.AddTransitionInternal(MergeTransitions(incoming, epsilon), optimizer); } if (!isStartState) { RemoveTransitionInternal(epsilon, optimizer); } } if (IncomingTransitions.Count == 1 && IncomingTransitions.First().IsEpsilon) { Transition epsilon = IncomingTransitions.First(); State sourceState = epsilon.SourceState; foreach (var outgoing in OutgoingTransitions.ToArray()) { if (!isStartState) { this.RemoveTransitionInternal(outgoing, optimizer); } sourceState.AddTransitionInternal(MergeTransitions(epsilon, outgoing), optimizer); } epsilon.SourceState.RemoveTransitionInternal(epsilon, optimizer); } }
protected virtual Network BuildNetworkImpl() { BindRules(); HashSet<State> states = GetAllStates(Rules); HashSet<State> reachableStates = GetReachableStates(Rules); HashSet<State> ruleStartStates = new HashSet<State>(Rules.Where(i => i.IsStartRule).Select(i => i.StartState), ObjectReferenceEqualityComparer<State>.Default); StateOptimizer optimizer = new StateOptimizer(states); Dictionary<int, RuleBinding> stateRules = new Dictionary<int, RuleBinding>(); foreach (var rule in Rules) GetRuleStates(optimizer, rule, rule.StartState, stateRules); Dictionary<int, RuleBinding> contextRules = new Dictionary<int, RuleBinding>(); foreach (var state in reachableStates) GetContextRules(state, stateRules, contextRules); #if !OLD_OPTIMIZER optimizer.Optimize(ruleStartStates); RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates); #else foreach (var state in states) state.RemoveExtraEpsilonTransitions(optimizer, ruleStartStates.Contains(state)); foreach (var state in states) state.AddRecursiveTransitions(optimizer); RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates); //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dot"); //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dgml"); int skippedCount = 0; int optimizedCount = 0; foreach (var state in reachableStates) { bool skip = false; /* if there are no incoming transitions and it's not a rule start state, * then the state is unreachable and will be removed so there's no need to * optimize it. */ if (!ruleStartStates.Contains(state) && state.OutgoingTransitions.Count > 0) { if (state.IncomingTransitions.Count == 0) skip = true; if (!skip && state.IncomingTransitions.All(i => i.IsEpsilon)) skip = true; if (!skip && !state.IncomingTransitions.Any(i => i.IsMatch) && !state.OutgoingTransitions.Any(i => i.IsMatch)) { bool incomingPush = state.IncomingTransitions.Any(i => i is PushContextTransition); bool incomingPop = state.IncomingTransitions.Any(i => i is PopContextTransition); bool outgoingPush = state.OutgoingTransitions.Any(i => i is PushContextTransition); bool outgoingPop = state.OutgoingTransitions.Any(i => i is PopContextTransition); if ((incomingPop && !outgoingPush) || (incomingPush && !outgoingPop)) skip = true; } } if (skip) { skippedCount++; continue; } state.Optimize(optimizer); optimizedCount++; } HashSet<State> reachableOptimizedStates = GetReachableStates(Rules); int removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates); foreach (var state in reachableOptimizedStates) { if (!state.IsOptimized && (state.OutgoingTransitions.Count == 0 || state.IncomingTransitions.Any(i => i.IsRecursive))) { bool hadTransitions = state.OutgoingTransitions.Count > 0; state.Optimize(optimizer); if (hadTransitions) removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates); } } //RemoveUnreachableStates(Rules, reachableStates, ruleStartStates); //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dot"); //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dgml"); #if false foreach (var rule in ruleBindings) OptimizeRule(rule, ruleStartStates); #endif reachableOptimizedStates = GetReachableStates(Rules); foreach (var state in reachableOptimizedStates) state.Optimize(optimizer); RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates); reachableOptimizedStates = GetReachableStates(Rules); //stateRules = RenumberStates(reachableOptimizedStates, reachableStates, stateRules); #endif return new Network(this, optimizer, Rules, stateRules, contextRules); }
private static void ExtractStatesAndTransitions(StateOptimizer optimizer, RuleBinding currentRule, State currentState, HashSet<State> states, HashSet<Transition> transitions, Dictionary<int, RuleBinding> stateRules, Dictionary<int, RuleBinding> contextRules) { if (!states.Add(currentState)) return; currentRule = currentRule ?? stateRules[currentState.Id]; foreach (var transition in currentState.OutgoingTransitions) { transitions.Add(transition); var nextRule = transition.IsContext ? null : currentRule; ExtractStatesAndTransitions(optimizer, nextRule, transition.TargetState, states, transitions, stateRules, contextRules); // if (transitions.Add(transition)) // { // if (transition.IsContext) // { // PushContextTransition pushContext = transition as PushContextTransition; // if (pushContext != null) // { // foreach (var popTransition in optimizer.GetPopContextTransitions(pushContext)) // { // // the matching pop transitions should always end in this rule // Contract.Assert(popTransition.ContextIdentifiers.Last() == pushContext.ContextIdentifiers.First()); //#if ALL_CHECKS // // matching is symmetric // Contract.Assert(popTransition.PushTransitions.Contains(pushContext)); //#endif // // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition // Contract.Assert(popTransition.SourceState != null); // ExtractStatesAndTransitions(optimizer, currentRule, popTransition.TargetState, states, transitions, stateRules, contextRules); // } // ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules); // continue; // } // PopContextTransition popContext = transition as PopContextTransition; // if (popContext != null) // { // foreach (var pushTransition in optimizer.GetPushContextTransitions(popContext)) // { // // the matching push transitions should always start in this rule // Contract.Assert(pushTransition.ContextIdentifiers.First() == popContext.ContextIdentifiers.Last()); //#if ALL_CHECKS // // matching is symmetric // Contract.Assert(pushTransition.PopTransitions.Contains(popContext)); //#endif // // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition // Contract.Assert(pushTransition.SourceState != null); // } // ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules); // continue; // } // throw new InvalidOperationException("Unrecognized context transition."); // } // else // { // ExtractStatesAndTransitions(optimizer, currentRule, transition.TargetState, states, transitions, stateRules, contextRules); // } // } } foreach (var transition in currentState.IncomingTransitions) { transitions.Add(transition); var nextRule = transition.IsContext ? null : currentRule; ExtractStatesAndTransitions(optimizer, nextRule, transition.SourceState, states, transitions, stateRules, contextRules); } }
protected virtual Network BuildNetworkImpl() { BindRules(); HashSet <State> states = GetAllStates(Rules); HashSet <State> reachableStates = GetReachableStates(Rules); HashSet <State> ruleStartStates = new HashSet <State>(Rules.Where(i => i.IsStartRule).Select(i => i.StartState), ObjectReferenceEqualityComparer <State> .Default); StateOptimizer optimizer = new StateOptimizer(states); Dictionary <int, RuleBinding> stateRules = new Dictionary <int, RuleBinding>(); foreach (var rule in Rules) { GetRuleStates(optimizer, rule, rule.StartState, stateRules); } Dictionary <int, RuleBinding> contextRules = new Dictionary <int, RuleBinding>(); foreach (var state in reachableStates) { GetContextRules(state, stateRules, contextRules); } #if !OLD_OPTIMIZER optimizer.Optimize(ruleStartStates); RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates); #else foreach (var state in states) { state.RemoveExtraEpsilonTransitions(optimizer, ruleStartStates.Contains(state)); } foreach (var state in states) { state.AddRecursiveTransitions(optimizer); } RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates); //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dot"); //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dgml"); int skippedCount = 0; int optimizedCount = 0; foreach (var state in reachableStates) { bool skip = false; /* if there are no incoming transitions and it's not a rule start state, * then the state is unreachable and will be removed so there's no need to * optimize it. */ if (!ruleStartStates.Contains(state) && state.OutgoingTransitions.Count > 0) { if (state.IncomingTransitions.Count == 0) { skip = true; } if (!skip && state.IncomingTransitions.All(i => i.IsEpsilon)) { skip = true; } if (!skip && !state.IncomingTransitions.Any(i => i.IsMatch) && !state.OutgoingTransitions.Any(i => i.IsMatch)) { bool incomingPush = state.IncomingTransitions.Any(i => i is PushContextTransition); bool incomingPop = state.IncomingTransitions.Any(i => i is PopContextTransition); bool outgoingPush = state.OutgoingTransitions.Any(i => i is PushContextTransition); bool outgoingPop = state.OutgoingTransitions.Any(i => i is PopContextTransition); if ((incomingPop && !outgoingPush) || (incomingPush && !outgoingPop)) { skip = true; } } } if (skip) { skippedCount++; continue; } state.Optimize(optimizer); optimizedCount++; } HashSet <State> reachableOptimizedStates = GetReachableStates(Rules); int removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates); foreach (var state in reachableOptimizedStates) { if (!state.IsOptimized && (state.OutgoingTransitions.Count == 0 || state.IncomingTransitions.Any(i => i.IsRecursive))) { bool hadTransitions = state.OutgoingTransitions.Count > 0; state.Optimize(optimizer); if (hadTransitions) { removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates); } } } //RemoveUnreachableStates(Rules, reachableStates, ruleStartStates); //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dot"); //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dgml"); #if false foreach (var rule in ruleBindings) { OptimizeRule(rule, ruleStartStates); } #endif reachableOptimizedStates = GetReachableStates(Rules); foreach (var state in reachableOptimizedStates) { state.Optimize(optimizer); } RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates); reachableOptimizedStates = GetReachableStates(Rules); //stateRules = RenumberStates(reachableOptimizedStates, reachableStates, stateRules); #endif return(new Network(this, optimizer, Rules, stateRules, contextRules)); }
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; }
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); } } }
protected virtual int RemoveUnreachableStates(StateOptimizer optimizer, IEnumerable<RuleBinding> rules, HashSet<State> states, HashSet<State> ruleStartStates) { int removedCount = 0; while (true) { HashSet<State> reachableStates = GetReachableStates(rules); bool removed = false; foreach (var state in states) { // already removed (or a terminal state) if (state.OutgoingTransitions.Count == 0) continue; /* if there are no incoming transitions and it's not a rule start state, * then the state is unreachable so we remove it. */ if (!reachableStates.Contains(state)) { removedCount++; removed = true; foreach (var transition in state.OutgoingTransitions.ToArray()) state.RemoveTransition(transition, optimizer); } } if (!removed) break; } #if DEBUG int recursiveStates = GetReachableStates(rules).Count(i => i.HasRecursiveTransitions ?? true); #endif return removedCount; }
private bool AddRecursivePopTransitions(HashSet <State> visited, State currentState, Transition effectiveTransition, List <int> contexts, StateOptimizer optimizer) { Contract.Requires(visited != null); Contract.Requires(currentState != null); Contract.Requires(contexts != null); Contract.Ensures(visited.Count == Contract.OldValue(visited.Count)); Contract.Ensures(contexts.Count == Contract.OldValue(contexts.Count)); bool foundRecursive = false; foreach (var transition in currentState.OutgoingTransitions.Where(i => !i.IsRecursive && (i.IsEpsilon || (i is PopContextTransition))).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; } PopContextTransition recursive = new PopContextTransition(this, contexts); recursive.IsRecursive = true; AddTransitionInternal(recursive, optimizer); continue; } if (!visited.Add(transition.TargetState)) { continue; } try { AddRecursivePopTransitions(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 static void ExtractStatesAndTransitions(StateOptimizer optimizer, RuleBinding currentRule, State currentState, HashSet <State> states, HashSet <Transition> transitions, Dictionary <int, RuleBinding> stateRules, Dictionary <int, RuleBinding> contextRules) { if (!states.Add(currentState)) { return; } currentRule = currentRule ?? stateRules[currentState.Id]; foreach (var transition in currentState.OutgoingTransitions) { transitions.Add(transition); var nextRule = transition.IsContext ? null : currentRule; ExtractStatesAndTransitions(optimizer, nextRule, transition.TargetState, states, transitions, stateRules, contextRules); // if (transitions.Add(transition)) // { // if (transition.IsContext) // { // PushContextTransition pushContext = transition as PushContextTransition; // if (pushContext != null) // { // foreach (var popTransition in optimizer.GetPopContextTransitions(pushContext)) // { // // the matching pop transitions should always end in this rule // Contract.Assert(popTransition.ContextIdentifiers.Last() == pushContext.ContextIdentifiers.First()); //#if ALL_CHECKS // // matching is symmetric // Contract.Assert(popTransition.PushTransitions.Contains(pushContext)); //#endif // // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition // Contract.Assert(popTransition.SourceState != null); // ExtractStatesAndTransitions(optimizer, currentRule, popTransition.TargetState, states, transitions, stateRules, contextRules); // } // ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules); // continue; // } // PopContextTransition popContext = transition as PopContextTransition; // if (popContext != null) // { // foreach (var pushTransition in optimizer.GetPushContextTransitions(popContext)) // { // // the matching push transitions should always start in this rule // Contract.Assert(pushTransition.ContextIdentifiers.First() == popContext.ContextIdentifiers.Last()); //#if ALL_CHECKS // // matching is symmetric // Contract.Assert(pushTransition.PopTransitions.Contains(popContext)); //#endif // // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition // Contract.Assert(pushTransition.SourceState != null); // } // ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules); // continue; // } // throw new InvalidOperationException("Unrecognized context transition."); // } // else // { // ExtractStatesAndTransitions(optimizer, currentRule, transition.TargetState, states, transitions, stateRules, contextRules); // } // } } foreach (var transition in currentState.IncomingTransitions) { transitions.Add(transition); var nextRule = transition.IsContext ? null : currentRule; ExtractStatesAndTransitions(optimizer, nextRule, transition.SourceState, states, transitions, stateRules, contextRules); } }
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); } } }