private static void WriteDiagram <TLetter>(ITestOutputHelper output, Dfa <TLetter> dfa) where TLetter : struct, IComparable <TLetter>, IEquatable <TLetter> { output.WriteLine("digraph G {"); output.WriteLine("graph[rankdir=\"LR\",dpi=65,size=100,forcelabels=true];"); output.WriteLine("\"{0}\" [peripheries=2,label=\"Accept\"];", Dfa <TLetter> .Accept); foreach (var symbolState in dfa.SymbolStates) { output.WriteLine("\"{0}\" [xlabel=\"{1}\"];", symbolState.Key, symbolState.Value); } // output.WriteLine("\"{0}\" [peripheries=2,label=\"Reject\"];", Dfa<TLetter>.Reject); // foreach (var state in dfa.States) { // output.WriteLine("\"{0}\" -> \"{1}\" [style=\"dashed\"];", state.Id, Dfa<TLetter>.Reject); // } foreach (var pair in dfa.States.SelectMany(s => s.Transitions.Select(t => new KeyValuePair <DfaState <TLetter>, KeyValuePair <Range <TLetter>, Id <DfaState <TLetter> > > >(s, t)))) { output.WriteLine("\"{0}\" -> \"{1}\" [label=\"{2}\"];", pair.Key.Id, pair.Value.Value, pair.Value.Key); } output.WriteLine("}"); }
private static Expression CreateLetterStateMachine(Dfa <LetterId> dfa, ParameterExpression paramState, Expression exprInput) { var ctor_IdDfaStateLetter = Reflect.GetConstructor(() => new Id <DfaState <LetterId> >(default(int))); var meth_LetterId_ToInt32 = Reflect <LetterId> .GetMethod(i => i.ToInt32()); var varInput = Expression.Variable(typeof(int), "input"); var varResult = Expression.Variable(typeof(SymbolId?), "result"); return(Expression.Block( typeof(SymbolId?), new[] { varInput, varResult }, Expression.Assign(varInput, exprInput is NewExpression exprInputNew && (exprInputNew.Constructor == ctor_LetterId) ? exprInputNew.Arguments.Single() : Expression.Call(exprInput, meth_LetterId_ToInt32)), Expression.Assign( paramState, Expression.New(ctor_IdDfaStateLetter, Expression.Switch( Expression.Call(paramState, Reflect <Id <DfaState <LetterId> > > .GetMethod(i => i.ToInt32())), Expression.Throw(new_InvalidOperationException, typeof(int)), dfa.States.OrderBy(s => s.Id).Select(state => Expression.SwitchCase( Expression.Switch( varInput, Expression.Constant(Dfa <LetterId> .Reject.ToInt32()), state .Transitions .GroupBy(p => p.Value.ToInt32(), p => p.Key) .Select(g => Expression.SwitchCase(dfa.SymbolStates.TryGetValue(new Id <DfaState <LetterId> >(g.Key), out var symbolId) ? Expression.Block( Expression.Assign(varResult, Expression.New(ctor_NullableSymbolId, Expression.New(ctor_SymbolId, Expression.Constant((int)symbolId)))), Expression.Constant(g.Key)) : (Expression)Expression.Constant(g.Key), g.SelectMany(r => r.Expand()).Select(i => Expression.Constant(i.ToInt32())))) .ToArray()), Expression.Constant(state.Id.ToInt32()) )).ToArray()))), varResult)); }
public static Expression <DfaStateMachine <LetterId, TLetter> > CreateExpression <TLetter>(Dfa <LetterId> dfa, Expression <Func <TLetter, LetterId> > inputToLetter) where TLetter : struct, IComparable <TLetter>, IEquatable <TLetter> { var paramState = Expression.Parameter(typeof(Id <DfaState <LetterId> >).MakeByRefType(), "state"); var paramInput = inputToLetter.Parameters.Single(); return(Expression.Lambda <DfaStateMachine <LetterId, TLetter> >(CreateLetterStateMachine(dfa, paramState, inputToLetter.Body), "DfaAlphabetStateMachine", new[] { paramState, paramInput })); }
public static Expression <DfaStateMachine <LetterId, LetterId> > CreateExpression(Dfa <LetterId> dfa) { var paramState = Expression.Parameter(typeof(Id <DfaState <LetterId> >).MakeByRefType(), "state"); var paramInput = Expression.Parameter(typeof(LetterId), "input"); return(Expression.Lambda <DfaStateMachine <LetterId, LetterId> >(CreateLetterStateMachine(dfa, paramState, paramInput), "DfaLetterStateMachine", new[] { paramState, paramInput })); }