public static NFA AnyOf(NFA left, NFA right) { var result = new NFA(); result.AddState(0, false); result.AddTransition(0, result.Add(left), Epsilon); result.AddTransition(0, result.Add(right), Epsilon); return(result); }
public static NFA Star(NFA input) { var result = new NFA(); var newFinal = result.NewState(); result.AddState(newFinal, true); var start = result.Add(input); var finals = result.final.Where(h => h != newFinal).ToArray(); foreach (var final in finals) { result.AddTransition(final, start, Epsilon); } result.AddTransition(newFinal, start, Epsilon); return(result); }
public static NFA Concat(NFA left, NFA right) { var result = new NFA(); result.Add(left); var leftFinals = result.final.ToArray(); result.final.Clear(); int rightInitial = result.Add(right); foreach (var final in leftFinals) { result.AddTransition(final, rightInitial, Epsilon); } return(result); }
public NFA Determinize() { NFA target = new NFA(); Stack <Tuple <int, HashSet <int> > > frontier = new Stack <Tuple <int, HashSet <int> > >(); Dictionary <HashSet <int>, int> seen = new Dictionary <HashSet <int>, int>(new SetStateComparer()); int set_key = 0; HashSet <int> set_initial = new HashSet <int>(); set_initial.Add(0); EpsilonClosure(set_initial); target.AddState(set_key, ContainsFinalState(set_initial)); frontier.Push(new Tuple <int, HashSet <int> >(set_key, set_initial)); seen[set_initial] = set_key; while (frontier.Count > 0) { var current = frontier.Pop(); var current_key = current.Item1; var current_set = current.Item2; bool hasA = false, hasB = false; foreach (var st in current_set) { foreach (var t in FindTransitions(st)) { if (t.Item3 == Epsilon) { continue; } else if (t.Item3 == 'a') { hasA = true; } else if (t.Item3 == 'b') { hasB = true; } if (hasA && hasB) { break; } } if (hasA && hasB) { break; } } var inputs = "ab"; if (!(hasA & hasB)) { inputs = hasA ? "a" : "b"; } foreach (var i in inputs) { HashSet <int> new_state = new HashSet <int>(); HashSet <char> new_transitions = new HashSet <char>(); foreach (var st in current_set) { foreach (var t in FindTransitions(st).Where(j => j.Item3 == i)) { new_transitions.Add(t.Item3); new_state.Add(t.Item2); } } EpsilonClosure(new_state); int seen_state_key; if (!seen.TryGetValue(new_state, out seen_state_key)) { set_key++; target.AddState(set_key, ContainsFinalState(new_state)); foreach (var t in new_transitions) { target.AddTransition(current_key, set_key, t); } frontier.Push(new Tuple <int, HashSet <int> >(set_key, new_state)); seen[new_state] = set_key; } else { foreach (var t in new_transitions) { target.AddTransition(current_key, seen_state_key, t); } } } } return(target); }
public NFA Parse(string input) { //Shunting-Yard algorithm Stack <char> s = new Stack <char>(); List <char> q = new List <char>(); var c = input.GetEnumerator(); char prev = '\0'; while (c.MoveNext()) { switch (c.Current) { case 'a': case 'b': q.Add(c.Current); if (prev == 'a' || prev == 'b' || prev == ')') { s.Push('-'); } break; case '(': if (prev == 'a' || prev == 'b' || prev == ')') { s.Push('-'); } s.Push(c.Current); break; case '*': case '|': s.Push(c.Current); break; case ')': while (s.Count > 0 && s.Peek() != '(') { q.Add(s.Pop()); } s.Pop(); break; } prev = c.Current; } Stack <NFA> calc = new Stack <NFA>(); foreach (var i in q) { if (i == '*') { calc.Push(NFA.Star(calc.Pop())); } else if (i == '-') { var right = calc.Pop(); var left = calc.Pop(); calc.Push(NFA.Concat(left, right)); } else if (i == '|') { var right = calc.Pop(); var left = calc.Pop(); calc.Push(NFA.AnyOf(left, right)); } else { NFA nfa = new NFA(); nfa.AddState(0, false); nfa.AddState(1, true); nfa.AddTransition(0, 1, i); calc.Push(nfa); } } return(calc.Pop()); }