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;
                }
            }
        }