public Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext) { var body = new List <Expression>(); if (saveContext) { body.Add(Expression.Assign( emitter.ContextParameter, Expression.Convert(contextExpression, typeof(object)))); } if (this.Yield) { body.Add(Expression.Constant(this.Target.GetValueOrDefault(emitter.BreakState))); } else { body.Add(Expression.Assign( emitter.StateParameter, Expression.Constant(this.Target.GetValueOrDefault(emitter.BreakState)))); body.Add(Expression.Goto( emitter.StartLabel, typeof(int))); } return(Expression.Block(body)); }
public Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext) { var body = new List <Expression>(); if (saveContext) { body.Add(Expression.Assign( emitter.ContextParameter, Expression.Convert( contextExpression, typeof(object)))); } var computeState = emitter.ReplaceBuildersByIds(this.computeState, emitter.InputParameter, contextExpression); if (this.Yield) { body.Add(computeState.Body); } else { body.Add(Expression.Assign( emitter.StateParameter, computeState.Body)); body.Add(Expression.Goto( emitter.StartLabel, typeof(int))); } return(body.Count == 1 ? body[0] : Expression.Block(body)); }
public void TestCounter(int expectedCount, string input) { // Define the state machine var root = new StateSwitchBuilder <char, char, int>(); root.On('\n', i => false); root.On((i, ctx) => false); root.On('\n').Do(i => i + 1).Yield(root); root.Default.Yield(root); // Compile the state machine var emitter = new StateMachineEmitter <char, char>(root, EquatableConditionEmitter <char> .Default); emitter.OnEnter <object>((i, d) => this.output.WriteLine("+")); emitter.OnLeave <object>((i, d) => this.output.WriteLine("-")); var stateExpr = emitter.Emit(); this.output.WriteLine(stateExpr.ToReadableString()); var stateFn = stateExpr.Compile(); // Run the state machine for some input var state = 0; object context = 0; foreach (var ch in input) { stateFn(ch, ref state, ref context); } // The context is now an integer with the number of newlines this.output.WriteLine(context.ToString()); Assert.Equal(expectedCount, (int)context); Assert.True(state >= 0); }
public override Expression EmitCondition(StateMachineEmitter <TComparand, TInput> emitter, ParameterExpression varContext) { var condition = emitter.ConditionEmitter.Emit(this.Comparand, emitter.InputParameter); if (this.Condition == null) { return(condition); } return(Expression.AndAlso( condition, emitter.ReplaceBuildersByIds(this.Condition, varContext).Body)); }
public void TestTypedContext() { var emitter = new StateMachineEmitter <char, char, ITestOutputHelper>(EquatableConditionEmitter <char> .Default); emitter.Root.Default.Do((ch, ctx) => ctx.WriteLine(ch.ToString())).Yield(); var stateExpr = emitter.Emit(); var stateFn = stateExpr.Compile(); var state = 0; stateFn('X', ref state, this.output); Assert.NotEqual(0, state); }
public void ExpressionReplaceTest() { var root = new StateSwitchBuilder <bool, bool, ITestOutputHelper>(); var emitter = new StateMachineEmitter <bool, bool>(root, EquatableConditionEmitter <bool> .Default); root.Default.Do(o => o.WriteLine(((int)root).ToString())); var stateExpr = emitter.Emit(); var stateFn = stateExpr.Compile(); var state = 0; object context = this.output; Assert.False(stateFn(true, ref state, ref context)); }
public void TestMergeOptimization() { // Define the state machine var root = new StateSwitchBuilder <char, char, int>(); root.On('x', i => false).Yield(root); root.On('a').Yield(root); root.On('x').Yield(root); root.On('b').Yield(root); // Compile the state machine var emitter = new StateMachineEmitter <char, char>(root, EquatableConditionEmitter <char> .Default); var stateExpr = emitter.Emit(); this.output.WriteLine(stateExpr.ToReadableString()); }
public void TestRangeSet(bool accept, string input) { var root = new StateSwitchBuilder <RangeSet <char>, char, ITestOutputHelper>(); var emitter = new StateMachineEmitter <RangeSet <char>, char>(root, RangesConditionEmitter <RangeSet <char>, char> .Default); root.OnSequence("test").Do(o => o.WriteLine("Done")).Yield(-2); root.On(new RangeSet <char>(" \t\r\n")).Yield(o => (int)root); var stateExpr = emitter.Emit(); var stateFn = stateExpr.Compile(); var state = 0; object context = this.output; foreach (var ch in input) { this.output.WriteLine(stateFn(ch, ref state, ref context).ToString()); } Assert.Equal(accept, state == -2); }
public override Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext) { emitter.AssertCanChangeContext(); saveContext = true; return(base.Emit(emitter, emitter.ReplaceBuildersByIds(this.transition, emitter.StateParameter, contextExpression).Body, ref saveContext)); }
public override Expression EmitCondition(StateMachineEmitter <TComparand, TInput> emitter, ParameterExpression varContext) { return(emitter.ReplaceBuildersByIds(this.Condition, emitter.InputParameter, varContext).Body); }
public virtual Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext) { return(this.Next.Emit(emitter, contextExpression, ref saveContext)); }
public override Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext) { return(Expression.Block( emitter.ReplaceBuildersByIds(this.action, emitter.StateParameter, contextExpression).Body, base.Emit(emitter, contextExpression, ref saveContext))); }
public StateReferenceReplacer(StateMachineEmitter <TComparand, TInput> emitter) { this.emitter = emitter; }
public abstract Expression EmitCondition(StateMachineEmitter <TComparand, TInput> emitter, ParameterExpression varContext);
/// <summary>Emits the state machine fragment as <see cref="Expression" />.</summary> /// <param name="emitter">The emitter.</param> /// <returns>An Expression.</returns> internal abstract Expression Emit(StateMachineEmitter <TComparand, TInput> emitter);