public string GenerateCS() { StringBuilder code = new StringBuilder(); BDD finalStateBDD = solver.False; BDD sinkStateBDD = solver.False; foreach (int q in automaton.GetStates()) { if (automaton.IsFinalState(q)) { finalStateBDD = finalStateBDD.Or(solver.MkCharConstraint((char)q)); } if (automaton.IsLoopState(q) && automaton.GetMovesCountFrom(q) == 1) { sinkStateBDD = sinkStateBDD.Or(solver.MkCharConstraint((char)q)); } } var ranges = finalStateBDD.ToRanges(); string finalPred = this.helper_predicates.GeneratePredicate(finalStateBDD); string sinkPred = this.helper_predicates.GeneratePredicate(sinkStateBDD); code.Append(String.Format(@" namespace {0} {{ public class {1} : Microsoft.Automata.IDeterministicFiniteAutomaton {{ System.Func<char, int>[] delta = new System.Func<char, int>[{2}]; int prevStartIndex = 0; int currIndex = 0; public System.Func<char, int>[] Delta {{ get {{return delta; }} }} public bool IsFinalState(int x) {{ return {3}; }} public bool IsSinkState(int x) {{ return {4}; }} //return the state from the given state after reading the input public int Transition(int state, params char[] input) {{ int x = state; for (int i = 0; i < input.Length; i++) {{ x = delta[x](input[i]); if ({4}) return x; }} return x; }} public {1}() {{", namespacename, classname, automaton.StateCount, finalPred, sinkPred)); for (int q = 0; q < automaton.StateCount; q++) { code.Append(String.Format(@" delta[{0}] = x => {{", q)); var path = solver.True; foreach (var move in automaton.GetMovesFrom(q)) { path = solver.MkDiff(path, move.Label); if (path == solver.False) //this is the last else case { code.Append(String.Format(@" return {0};", move.TargetState)); } else { code.Append(String.Format(@" if ({0}) return {1};", helper_predicates.GeneratePredicate(move.Label), move.TargetState)); } } code.Append(String.Format(@" }};")); } code.Append(String.Format(@" }} ")); //adds a static IsMatch method code.Append(String.Format(@" public bool IsMatch(string input) {{ var cs = input.ToCharArray(); int k = input.Length; int x = 0; int i = -1;", namespacename, classname)); Predicate <int> IsFinalSink = (q => (automaton.GetMovesCountFrom(q) == 1 && automaton.IsLoopState(q) && automaton.IsFinalState(q) && automaton.GetMoveFrom(q).Label.IsFull)); Predicate <int> IsNoninalSink = (q => (automaton.GetMovesCountFrom(q) == 1 && automaton.IsLoopState(q) && !automaton.IsFinalState(q) && automaton.GetMoveFrom(q).Label.IsFull)); Predicate <int> IsInitialSource = (q => q == automaton.InitialState && automaton.GetMovesCountTo(q) == 0); for (int q = 0; q < automaton.StateCount; q++) { if (IsFinalSink(q)) { code.Append(String.Format(@" State{0}: return true;", q)); } else if (IsNoninalSink(q)) { code.Append(String.Format(@" State{0}: return false;", q)); } else { if (!IsInitialSource(q)) { code.Append(String.Format(@" State{0}:", q)); } code.Append(String.Format(@" i += 1; if (i == k) return {0}; x = (int)cs[i];", automaton.IsFinalState(q).ToString().ToLower())); //--------------------------------------------------------------------- //many potential optimizations can be made in generating the conditions //--------------------------------------------------------------------- var path = solver.True; foreach (var move in automaton.GetMovesFrom(q)) { path = solver.MkDiff(path, move.Label); if (path == solver.False) //this is the last else case { BDD qBDD = solver.MkCharConstraint((char)q); code.Append(String.Format(@" goto State{0};", move.TargetState)); } else { code.Append(String.Format(@" if ({0}) goto State{1};", helper_predicates.GeneratePredicate(move.Label), move.TargetState)); } } } } code.Append(@" }"); //adds a static GenerateMatches method code.Append(String.Format(@" public System.Collections.Generic.IEnumerable<System.Tuple<int,int>> GenerateMatches(string input) {{ var cs = input.ToCharArray(); int i0 = 0; int q = 0; for (int i = 0; i < cs.Length; i++) {{ if (q == 0) {{ i0 = i; }} q = this.delta[q](cs[i]); if (this.IsFinalState(q)) {{ yield return new System.Tuple<int,int>(i0,i); q = 0; }} }} }}", classname)); code.Append(helper_predicates.ToString()); code.Append(@" } }"); return(code.ToString()); }
public string GenerateCS() { StringBuilder code = new StringBuilder(); var stack = new SimpleStack <int>(); var set = new HashSet <int>(); stack.Push(automaton.InitialState); set.Add(automaton.InitialState); code.Append(String.Format(@" namespace {0} {{ public class {1} {{ public static bool IsMatch(string input) {{ var cs = input.ToCharArray(); int k = input.Length; int c = 0; int i = -1;", namespacename, classname)); Predicate <int> IsFinalSink = (q => (automaton.GetMovesCountFrom(q) == 1 && automaton.IsLoopState(q) && automaton.IsFinalState(q) && automaton.GetMoveFrom(q).Label.IsFull)); Predicate <int> IsNonfinalSink = (q => (automaton.GetMovesCountFrom(q) == 0)); Predicate <int> IsInitialSource = (q => q == automaton.InitialState && automaton.GetMovesCountTo(q) == 0); while (stack.IsNonempty) { int q = stack.Pop(); bool q_is_complete = false; if (IsFinalSink(q)) { code.Append(String.Format(@" State{0}: return true;", q)); } else { if (!IsInitialSource(q)) { code.Append(String.Format(@" State{0}:", q)); } code.Append(String.Format(@" i += 1; if (i == k) return {0}; c = (int)cs[i];", automaton.IsFinalState(q).ToString().ToLower())); //--------------------------------------------------------------------- //many potential optimizations can be made in generating the conditions //--------------------------------------------------------------------- var path = solver.True; foreach (var move in automaton.GetMovesFrom(q)) { path = solver.MkDiff(path, move.Label); if (path == solver.False) //this is the last else case { code.Append(String.Format(@" goto State{0};", move.TargetState)); q_is_complete = true; } else { code.Append(String.Format(@" if ({0}) goto State{1};", helper_predicates.GeneratePredicate(move.Label), move.TargetState)); } if (set.Add(move.TargetState)) { stack.Push(move.TargetState); } } if (!q_is_complete) { //reject the input, this corresponds to q being a partial state //the implicit transition is to a deadend sink state code.Append(@" return false;"); } } } code.Append(@" }"); code.Append(helper_predicates.ToString()); code.Append(@" } }"); return(code.ToString()); }
string GenerateTransitionsFor(int i) { StringBuilder transitions = new StringBuilder(); var stack = new SimpleStack <int>(); var set = new HashSet <int>(); var automaton = automata[i]; stack.Push(automaton.InitialState); set.Add(automaton.InitialState); Predicate <int> IsFinalSink = (q => (automaton.GetMovesCountFrom(q) == 1 && automaton.IsLoopState(q) && automaton.IsFinalState(q) && automaton.GetMoveFrom(q).Label.IsFull)); Predicate <int> IsNonfinalSink = (q => (!automaton.IsFinalState(q) && (automaton.GetMovesCountFrom(q) == 0 || (automaton.GetMovesCountFrom(q) == 1 && automaton.IsLoopState(q))))); while (stack.IsNonempty) { int q = stack.Pop(); bool q_is_complete = false; if (IsFinalSink(q)) { transitions.Append(String.Format(@" State{0}: return true;", q)); } else if (IsNonfinalSink(q)) { transitions.Append(String.Format(@" State{0}: return false;", q)); } else { transitions.Append(String.Format(@" State{0}: if (i == k) return {1};", q, (automaton.IsFinalState(q) ? "true" : "false"))); if (automaton.GetMovesCountFrom(q) > 0) //q is a sink { transitions.Append(String.Format(@" if (!UTF8toUTF16(&r, &i, &c, k, str)) return false;")); //--------------------------------------------------------------------- //many potential optimizations can be made in generating the conditions //--------------------------------------------------------------------- var path = solver.True; foreach (var move in automaton.GetMovesFrom(q)) { path = solver.MkDiff(path, move.Label); if (path == solver.False) //this is the last else case { transitions.Append(String.Format(@" goto State{0};", move.TargetState)); q_is_complete = true; } else { transitions.Append(String.Format(@" if ({0}) goto State{1};", helper_predicates.GeneratePredicate(move.Label), move.TargetState)); } if (set.Add(move.TargetState)) { stack.Push(move.TargetState); } } } if (!q_is_complete) { //reject the input, this corresponds to q being a partial state //the implicit transition is to a deadend sink state transitions.Append(@" return false;"); } } } return(transitions.ToString()); }