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}];
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 static 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(@"
}");
code.Append(helper_predicates.ToString());
code.Append(@"
}
}");
return(code.ToString());
}