public static FA Build(FA dfa1, FA dfa2, Func <State, State, bool> isFinal) { EnsureDfa(dfa1); EnsureDfa(dfa2); dfa1 = Complete(dfa1); dfa2 = Complete(dfa2); EnsureComplete(dfa1); EnsureComplete(dfa2); var cross = new State[dfa1.States.Count, dfa2.States.Count]; var t1 = dfa1.States.Select(s => GetTransitions(s)).ToList(); var t2 = dfa2.States.Select(s => GetTransitions(s)).ToList(); for (var n1 = 0; n1 < dfa1.States.Count; n1 += 1) { for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1) { cross[n1, n2] = new State(isFinal(dfa1.States[n1], dfa2.States[n2])); } } for (var n1 = 0; n1 < dfa1.States.Count; n1 += 1) { for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1) { var state = cross[n1, n2]; var ctranses = GetMerge(t1[n1], t2[n2]); foreach (var ctrans in ctranses) { state.Add(Codepoints.From(ctrans.Range.Min, ctrans.Range.Max), cross[ctrans.Target1, ctrans.Target2]); } } } var dfa = From(cross[0, 0]); EnsureComplete(dfa); return(dfa.RemoveDead().Minimize()); }
public static FA Complete(FA dfa) { EnsureDfa(dfa); State sink = null; foreach (var state in dfa.States) { var rest = UnicodeSets.Any(); foreach (var transition in state.Transitions) { rest = rest.ExceptWith(transition.Terminal); } if (!rest.IsEmpty) { if (sink == null) { sink = new State(); sink.Add(Codepoints.Any, sink); } state.Add(Codepoints.From(rest), sink); } } if (sink != null) { sink.Id = dfa.States.Count; dfa.States.Add(sink); } EnsureComplete(dfa); return(dfa); }
public static FA ToDfa(FA nfa) { if (nfa.Final == null) { EnsureDfa(nfa); return(nfa); } var once = new UniqueQueue <Closure>(); var start = new Closure(nfa.Start, nfa.Final); once.Enqueue(start); while (once.Count > 0) { var closure = once.Dequeue(); var transitions = closure.UnambiguateTransitions(); foreach (var transition in transitions) { var terminal = transition.Key; var targets = transition.Value; var targetClosure = new Closure(targets, nfa.Final); once.Enqueue(targetClosure, out targetClosure); var target = targetClosure.DfaState; closure.DfaState.Add(Codepoints.From(terminal), target); } } var dfa = From(start.DfaState); EnsureDfa(dfa); return(dfa); }