public static SwitchGenerator Sparse( IntArrow<int>[] intervalToValue, int defaultValue, IntInterval possibleBounds, IIntFrequency frequency = null) { var result = new SparseSwitchGenerator(intervalToValue, defaultValue, possibleBounds, frequency); return result; }
public SparseSwitchGenerator( IntArrow<int>[] intArrows, int defaultValue, IntInterval possibleBounds, IIntFrequency frequency = null) : this(new MutableIntMap<int>(intArrows, defaultValue), possibleBounds, frequency) { }
public Decision Build(IntArrow<int>[] intArrows) { Decision result = TrySingleKey(intArrows, defaultAction); if (result == null) { var upperBounds = ToUpperBoundsMap(intArrows, defaultAction); result = Build(0, upperBounds.Length, upperBounds); } return result; }
private static Decision TrySingleKey(IntArrow<int>[] intArrows, int defaultValue) { if (intArrows.Length == 1) { var interval = intArrows[0].Key; if (interval.First == interval.Last) { var branch = new RelationalBranchDecision(RelationalOperator.Equal, interval.First); branch.Left = new ActionDecision(intArrows[0].Value); branch.Right = new ActionDecision(defaultValue); return branch; } } return null; }
public void Normalize() { double sum = 0.0; foreach (var arrow in arrows) { sum += arrow.Value * arrow.Key.Size; } int count = arrows.Count; for (int i = 0; i != count; ++i) { var old = arrows[i]; arrows[i] = new IntArrow <double>(old.Key, old.Value / sum); } }
private static KeyValuePair<int, int>[] ToUpperBoundsMap(IntArrow<int>[] intArrows, int defaultValue) { var resultList = new List<KeyValuePair<int, int>>(intArrows.Length); int prev = int.MinValue; foreach (var pair in intArrows) { int first = pair.Key.First; int last = pair.Key.Last; if (first > (1 + prev)) // gap between this and prior interval { resultList.Add(new KeyValuePair<int, int>(first - 1, defaultValue)); resultList.Add(new KeyValuePair<int, int>(last, pair.Value)); } else if (resultList.Count != 0 && resultList[resultList.Count - 1].Value == pair.Value) { resultList[resultList.Count - 1] = new KeyValuePair<int, int>(last, pair.Value); } else { resultList.Add(new KeyValuePair<int, int>(last, pair.Value)); } prev = last; } #if false Console.WriteLine("Upperbounds:"); for (int i = 0; i != resultList.Count; ++i) { var pair = resultList[i]; Console.WriteLine("{0}: ubound={1}, value={2}", i, pair.Key, pair.Value); } #endif return resultList.ToArray(); }
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 UniformIntFrequency(IntInterval bounds) { double elementProbability = bounds.IsEmpty ? 0 : (1.0 / bounds.LongSize); this.arrow = new IntArrow<double>(bounds, elementProbability); }
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() ; }