public static FA From(string sequence) { Debug.Assert(!string.IsNullOrEmpty(sequence)); var start = new State(); var current = start; var next = (State?)null; foreach (var ch in sequence) { next = new State(); current.Add(Integers.From(ch), next); current = next; } Debug.Assert(next != null); return(FA.From(start, next)); }
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.Set); } if (!rest.IsEmpty) { if (sink == null) { sink = new State(); sink.Add(Integers.Any, sink); } state.Add(Integers.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(Integers.From(terminal), target); } } var dfa = From(start.DfaState); EnsureDfa(dfa); return(dfa); }
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) { var state1 = dfa1.States[n1]; for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1) { var state2 = dfa2.States[n2]; var newState = new State(isFinal(state1, state2)); if (state1.IsPayload && !state2.IsPayload) { newState.AddPayload(state1); } else if (!state1.IsPayload && state2.IsPayload) { newState.AddPayload(state2); } else if (state1.IsPayload && state2.IsPayload) { Debug.Assert(true); #if true if (state1.Transitions.Count == 1 && state1.Transitions[0].Set.IsAny) { newState.AddPayload(state1); } else if (state2.Transitions.Count == 1 && state2.Transitions[0].Set.IsAny) { newState.AddPayload(state2); } else { if (state1.Payload > state2.Payload) { newState.AddPayload(state1); } else { newState.AddPayload(state2); } //throw new InternalException("missing tie break"); } #endif } cross[n1, n2] = newState; } } 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(Integers.From(ctrans.Range.Min, ctrans.Range.Max), cross[ctrans.Target1, ctrans.Target2]); } } } var dfa = From(cross[0, 0]); EnsureComplete(dfa); dfa = dfa.RemoveDead(); dfa = dfa.Minimize(); dfa = dfa.RemoveDead(); return(dfa); }
public static FA From(int first, int last) => Single(Integers.From(first, last));
public static FA From(char ch) => Single(Integers.From(ch));