private static CodeStatement GenerateMainLoop <TDfa, TDfaState>(TDfa dfa, CodeVariableReferenceExpression lexerStateVariable) where TDfa : AbstractDfa <TDfaState, char> where TDfaState : AbstractDfaState <TDfaState, char> { var switchGenerator = new SwitchGenerator <TDfa, TDfaState>(dfa, lexerStateVariable); return(switchGenerator.MakeStatement()); }
public void GenerateCurrentSwitchOff() { var context = Substitute.For <ICircuitContext>(); context.ModelsRegistry.FindModel <CurrentSwitchModel>(Arg.Any <string>()).Returns(new CurrentSwitchModel("WModel")); var parameters = new ParameterCollection { new ValueParameter("1"), new ValueParameter("0"), new IdentifierParameter("V3"), new WordParameter("model"), new WordParameter("Off"), }; var generator = new SwitchGenerator(); var @switch = generator.Generate("w1", "w1", "w", parameters, context); Assert.NotNull(@switch); Assert.IsType <CurrentSwitch>(@switch); Assert.False(@switch.ParameterSets.Get <SpiceSharp.Components.SwitchBehaviors.BaseParameters>().ZeroState); }
public void GenerateVoltageSwitch() { var context = Substitute.For <ICircuitContext>(); context.ModelsRegistry.FindModel <VoltageSwitchModel>(Arg.Any <string>()).Returns(new VoltageSwitchModel("SModel")); var parameters = new ParameterCollection { new ValueParameter("1"), new ValueParameter("0"), new ValueParameter("2"), new ValueParameter("0"), new WordParameter("model"), new WordParameter("On"), }; var generator = new SwitchGenerator(); var @switch = generator.Generate("s1", "s1", "s", parameters, context); Assert.NotNull(@switch); Assert.IsType <VoltageSwitch>(@switch); Assert.True(@switch.ParameterSets.Get <SpiceSharp.Components.SwitchBehaviors.BaseParameters>().ZeroState); }
public void Build(EmitSyntax emit) { // Debug.WriteLine("DFA for " + descriptor.Name + ":"); // Debug.WriteLine(dfa); int failState = dfa.StateCount; var locals = emit.Locals; var labels = emit.Labels; var FIN = labels.Generate(); var current = locals.Generate("ch"); var Lgoto = new Ref <Labels> [dfa.StateCount + 1]; // label for incrementing ch position var Mgoto = new Ref <Labels> [dfa.StateCount]; // assing ch using current position var Tgoto = new Ref <Labels> [dfa.StateCount]; // transition dispatching switch-code for (int i = 0; i != dfa.StateCount; ++i) { Lgoto[i] = labels.Generate().GetRef(); Mgoto[i] = labels.Generate().GetRef(); Tgoto[i] = labels.Generate().GetRef(); } Lgoto[failState] = FIN.GetRef(); emit .Local(current, emit.Types.Char) .Ldarg(0).Ldfld((ScanCursor c) => c.InnerState) .Switch(Mgoto) .Br(Lgoto[0]) ; foreach (var S in dfa.EnumerateStates()) { int state = S.Index; emit .Label(Lgoto[state].Def); if (state != dfa.Start) { // ++Cursor emit .Ldarg(0) // for Stfld .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor) .Ldc_I4_1() .Add() .Stfld((ScanCursor c) => c.Cursor) ; } // If state is accepring then remember position // in Marker and save corresponding ActionId. if (S.IsAccepting) { int actionCount = 0; foreach (var action in S.Actions) { emit .Ldarg(0) .Ldfld((ScanCursor c) => c.Actions) .Ldc_I4(actionCount++) .Ldc_I4(action) .Stelem_I4() ; } emit .Ldarg(0) .Ldc_I4(actionCount) .Stfld((ScanCursor c) => c.ActionCount) ; emit .Ldarg(0) .Ldc_I4(S.EnvelopeId) .Stfld((ScanCursor c) => c.EnvelopeId) ; emit .Ldarg(0) .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor) .Stfld((ScanCursor c) => c.Marker); // Save line/column information emit // cursor.MarkerLine = cursor.CursorLine; .Ldarg(0) .Ldarg(0) .Ldfld((ScanCursor c) => c.CursorLine) .Stfld((ScanCursor c) => c.MarkerLine) // cursor.MarkerLineStart = cursor.CursorLineStart; .Ldarg(0) .Ldarg(0) .Ldfld((ScanCursor c) => c.CursorLineStart) .Stfld((ScanCursor c) => c.MarkerLineStart) ; } if (S.IsNewline) { emit // ++cursor.CursorLine; .Ldarg(0) .Ldarg(0) .Ldfld((ScanCursor c) => c.CursorLine) .Ldc_I4_1() .Add() .Stfld((ScanCursor c) => c.CursorLine) // cursor.CursorLineStart = cursor.Cursor; .Ldarg(0) .Ldarg(0) .Ldfld((ScanCursor c) => c.Cursor) .Stfld((ScanCursor c) => c.CursorLineStart) ; } emit .Label(Mgoto[state].Def) // Get current input symbol .Ldarg(0).Ldfld((ScanCursor c) => c.Buffer) .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor) .Ldelem_U2() .Stloc(current.GetRef()) // Label for tunneling .Label(Tgoto[state].Def) ; if (S.IsFinal && state != 0) { emit .Br(FIN.GetRef()); continue; } int checkSentinelState = failState + 1; var stateRealTransitions = dfa.EnumerateRealTransitions(S).ToList(); // Find custom sentinel transtion int customSentinelToState = -1; var customSentinelTransitionIndex = stateRealTransitions.FindIndex(pair => pair.Key.Contains(Sentinel)); if (customSentinelTransitionIndex >= 0) { customSentinelToState = stateRealTransitions[customSentinelTransitionIndex].Value; } // Sentinel check transiiton var sentinelTransition = new IntArrow <int>(Sentinel, checkSentinelState); stateRealTransitions.Insert(0, sentinelTransition); var generator = SwitchGenerator.Sparse( stateRealTransitions.ToArray(), failState, UnicodeIntSetType.UnicodeInterval, frequency: UnicodeFrequency.Default); generator.Build( emit, il => il.Ldloc(current.GetRef()), (EmitSyntax il, int value) => { if (value == checkSentinelState) { var handleSentinelCharLabel = (customSentinelToState >= 0) ? Lgoto[customSentinelToState] : FIN.GetRef(); // return for buffer filling if Cursor == Limit, // otherwise transite on char il .Ldarg(0).Ldfld((ScanCursor c) => c.Limit) .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor) .Bne_Un(handleSentinelCharLabel) // Return for buffer filling .Ldarg(0) .Ldc_I4(state) .Stfld((ScanCursor c) => c.InnerState) .Ldc_I4(1) .Ret() ; } else if (value == failState && S.Tunnel >= 0) { // Tunnel-jump to other state and verify current // input again in that state. il.Br(Tgoto[S.Tunnel]); } else { // Transite to the valid or failed state il.Br(Lgoto[value]); } }); } // Return to the last accepted position and report accept stage emit .Label(FIN) .Ldc_I4(0) .Ret() ; }
public void BuildBody( EmitSyntax emit, LanguageData data, Ref <Args> tokenId, Ref <Args> oldValue, Ref <Args> newValue, Ref <Args> ctx, Ref <Args> lookbackStart) { var mergers = data.Grammar.Mergers; if (mergers.Count == 0) { emit .Ldarg(oldValue) .Ret(); return; } var contextResolverCode = new ContextCode( emit, il => il.Ldarg(ctx), il => il.Ldarg(lookbackStart), data, data.Grammar.GlobalContextProvider, data.LocalParseContexts); IActionCode code = new MergeCode(emit, contextResolverCode) { LoadOldValue = il => il.Ldarg(oldValue), LoadNewValue = il => il.Ldarg(newValue), }; var tokenToRuleIndex = new MutableIntMap <int>( mergers.Select( merger => new IntArrow <int>(merger.Symbol.Index, merger.Index))); tokenToRuleIndex.DefaultValue = -1; var ids = mergers.Select(m => m.Symbol.Index); IntInterval possibleBounds = new IntInterval(ids.Min(), ids.Max()); var switchGenerator = SwitchGenerator.Sparse(tokenToRuleIndex, possibleBounds); switchGenerator.Build( emit, il => il.Ldarg(tokenId), (il, value) => { if (value < 0) { emit .Ldarg(newValue) .Ret(); } else { var merger = mergers[value]; var binding = merger.Joint.The <CilMerger>(); code = code .Do(binding.Context.Load) .Do(binding.ActionBuilder) .Emit(il2 => il2.Ret()) ; } }); emit .Ret(); }
public void LdContext(string contextName) { var contextRef = new ForeignContextRef(contextName); if (localContexts != null && localContexts.Length != 0) { var locals = localContexts.Where(lc => lc.Consumer.Equals(contextRef)).ToArray(); if (locals.Length != 0) { var END = emit.Labels.Generate().GetRef(); var labels = new Ref <Labels> [locals.Length + 1]; for (int i = 0; i != labels.Length; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } var map = (from i in Enumerable.Range(0, locals.Length) let lc = locals[i] select new IntArrow <int>(lc.StackState, i)) .ToArray(); var switchGenerator = SwitchGenerator.Sparse( map, labels.Length - 1, new IntInterval(0, short.MaxValue)); Expression <Action <IStackLookback <Msg> > > lookback = lb => lb.GetParentState(); switchGenerator.Build( emit, new Pipe <EmitSyntax>(il => il.Do(ldLookback).Call <IStackLookback <Msg> >(lookback)), (il, value) => { il.Label(labels[value].Def); if (value == locals.Length) { if (LdGlobalContext(contextName)) { il.Br(END); } else { il .Ldstr(new QStr("Internal error: missing global context : " + contextRef.UniqueName)) .Newobj((string msg) => new Exception(msg)) .Throw() ; } } else { var lc = locals[value]; var provider = lc.Provider.Joint.The <CilContextProvider>(); var context = provider.GetContext(contextName); context.Ld( il, il2 => il2 // Lookback for getting parent instance .Do(ldLookback) .Ldc_I4(lc.StackLookback) .Call((IStackLookback <Msg> lb, int backOffset) => lb.GetValueAt(backOffset)) .Ldfld((Msg msg) => msg.Value)); il.Br(END); } }); emit.Label(END.Def); return; } } if (!LdGlobalContext(contextName)) { throw new InvalidOperationException( "Context '" + contextName + "' is not accessible."); } }