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