internal static void EmitPart(FA gnfa, IList <int[]> prog)
        {
            // TODO: Make sure this is an actual GNFA and not just an NFA
            // NFA that is not a GNFA will not work
            gnfa = gnfa.ToGnfa();
            gnfa.TrimNeutrals();
            var rendered  = new Dictionary <FA, int>();
            var swFixups  = new Dictionary <FA, int>();
            var jmpFixups = new Dictionary <FA, int>();
            var l         = new List <FA>();

            gnfa.FillClosure(l);
            // move the accepting state to the end
            var fas  = gnfa.FirstAcceptingState;
            var afai = l.IndexOf(fas);

            l.RemoveAt(afai);
            l.Add(fas);
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                var fa = l[i];
                rendered.Add(fa, prog.Count);
                if (!fa.IsFinal)
                {
                    int swfixup = prog.Count;
                    prog.Add(null);
                    swFixups.Add(fa, swfixup);
                }

                /*if(ic-1!=i)
                 * {
                 *      if (0==fa.EpsilonTransitions.Count)
                 *      {
                 *              jmpFixups.Add(fa, prog.Count);
                 *              prog.Add(null);
                 *      }
                 * }*/
            }
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                var fa = l[i];
                if (!fa.IsFinal)
                {
                    var sw = new List <int>();
                    sw.Add(Switch);
                    int[] simple = null;
                    if (1 == fa.InputTransitions.Count && 0 == fa.EpsilonTransitions.Count)
                    {
                        foreach (var trns in fa.InputTransitions)
                        {
                            if (l.IndexOf(trns.Key) == i + 1)
                            {
                                simple = trns.Value;
                            }
                        }
                    }
                    if (null != simple)
                    {
                        if (2 < simple.Length || simple[0] != simple[1])
                        {
                            sw[0] = Set;
                            sw.AddRange(simple);
                        }
                        else
                        {
                            sw[0] = Char;
                            sw.Add(simple[0]);
                        }
                    }
                    else
                    {
                        foreach (var trns in fa.InputTransitions)
                        {
                            var dst = rendered[trns.Key];
                            sw.AddRange(trns.Value);
                            sw.Add(-1);
                            sw.Add(dst);
                        }
                        if (0 < fa.InputTransitions.Count && 0 < fa.EpsilonTransitions.Count)
                        {
                            sw.Add(-2);
                        }
                        else if (0 == fa.InputTransitions.Count)
                        {
                            sw[0] = Jmp;
                        }
                        foreach (var efa in fa.EpsilonTransitions)
                        {
                            var dst = rendered[efa];
                            sw.Add(dst);
                        }
                    }
                    prog[swFixups[fa]] = sw.ToArray();
                }

                var jfi = -1;
                if (jmpFixups.TryGetValue(fa, out jfi))
                {
                    var jmp = new int[2];
                    jmp[0]    = Jmp;
                    jmp[1]    = prog.Count;
                    prog[jfi] = jmp;
                }
            }
        }
Exemple #2
0
        internal static void EmitFAPart(FA fa, IList <int[]> prog)
        {
            //fa = fa.ToDfa();
            //fa.TrimDuplicates();
            //fa = fa.ToGnfa();
            if (fa.IsNeutral)
            {
                foreach (var efa in fa.EpsilonTransitions)
                {
                    fa = efa;
                }
            }
            var acc = fa.FillAcceptingStates();

            foreach (var afa in acc)
            {
                if (!afa.IsFinal)
                {
                    var ffa = new FA(true, afa.AcceptSymbol);
                    afa.EpsilonTransitions.Add(ffa);
                    afa.IsAccepting = false;
                }
            }
            var rendered  = new Dictionary <FA, int>();
            var swFixups  = new Dictionary <FA, int>();
            var jmpFixups = new Dictionary <FA, int>();
            var l         = new List <FA>();

            fa.FillClosure(l);
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                var reused = false;
                var cfa    = l[i];
                if (!cfa.IsFinal)
                {
                    rendered.Add(cfa, prog.Count);
                }
                else
                {
                    foreach (var r in rendered)
                    {
                        if (r.Key.IsFinal)
                        {
                            if (r.Key.IsAccepting && cfa.AcceptSymbol == r.Key.AcceptSymbol)
                            {
                                // we can reuse this
                                rendered.Add(cfa, r.Value);
                                reused = true;
                                break;
                            }
                        }
                    }
                    if (!reused)
                    {
                        rendered.Add(cfa, prog.Count);
                    }
                }

                if (!cfa.IsFinal)
                {
                    int swfixup = prog.Count;
                    prog.Add(null);                     // switch
                    swFixups.Add(cfa, swfixup);
                }
                else
                {
#if DEBUG
                    System.Diagnostics.Debug.Assert(cfa.IsAccepting);
#endif
                    if (!reused)
                    {
                        prog.Add(new int[] { Save, 1 });                         // save
                        prog.Add(new int[] { Match, cfa.AcceptSymbol });
                    }
                }
            }
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                var cfa = l[i];

                if (!cfa.IsFinal)
                {
                    var sw = new List <int>();
                    sw.Add(Switch);

                    var rngGrps = cfa.FillInputTransitionRangesGroupedByState();
                    foreach (var grp in rngGrps)
                    {
                        var dst = rendered[grp.Key];
                        sw.AddRange(grp.Value);
                        sw.Add(-1);
                        sw.Add(dst);
                    }
                    if (1 < sw.Count)
                    {
                        if (0 < cfa.EpsilonTransitions.Count)
                        {
                            sw.Add(-2);
                            foreach (var efa in cfa.EpsilonTransitions)
                            {
                                var dst = rendered[efa];
                                sw.Add(dst);
                            }
                        }
                    }
                    else
                    {
                        // basically a NOP. Will get removed
                        sw[0] = Jmp;
                        sw.Add(swFixups[cfa] + 1);
                    }
                    prog[swFixups[cfa]] = sw.ToArray();
                }

                var jfi = -1;
                if (jmpFixups.TryGetValue(cfa, out jfi))
                {
                    var jmp = new int[2];
                    jmp[0]    = Jmp;
                    jmp[1]    = prog.Count;
                    prog[jfi] = jmp;
                }
            }
        }