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();
        }
Beispiel #7
0
        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()
                ;
        }