private void CreateNFA(string input) { Stack<char> operatorStack = new Stack<char>(); var expandedInput = ConcatExpand(input); for (int i = 0; i < expandedInput.Length; i++) { char c = expandedInput[i]; if (char.IsLetterOrDigit(c)) Push(c); else if (operatorStack.Count == 0) operatorStack.Push(c); else if (c == '(') operatorStack.Push(c); else if (c == ')') { while (operatorStack.Peek() != '(') { var op = operatorStack.Pop(); if (op == (char)8) Concat(); else if (op == '*') Star(); else if (op == '|') Union(); else return; } operatorStack.Pop(); //pop up '(' } else { while (operatorStack.Count != 0 && Presedece(c, operatorStack.Peek())) { var op = operatorStack.Pop(); if (op == (char)8) Concat(); else if (op == '*') Star(); else if (op == '|') Union(); else return; } operatorStack.Push(c); } } while (operatorStack.Count > 0) { var op = operatorStack.Pop(); if (op == (char)8) Concat(); else if (op == '*') Star(); else if (op == '|') Union(); else return; } if (_operandStack.Count == 0) return; var A = _operandStack.Pop(); A.GetLastState().AcceptState = true; #if DEBUG if (A.GetFirstState() != null) { using (var stream = File.OpenWrite("NFA.txt")) { using (var sw = new StreamWriter(stream)) { HashSet<int> processedStates = new HashSet<int>(); Deque<State> unprocessedStates = new Deque<State>(); unprocessedStates.PushBack(A.GetFirstState()); while(unprocessedStates.Count>0) { var state = unprocessedStates.PopFront(); var labels = state.GetLabels(); foreach (var label in labels) { var destinationStates = state.GetStates(label); if (destinationStates != null) { foreach (var dest in destinationStates) { sw.WriteLine("Start:" + state.ToString() + "," + "End:" + dest.ToString() + "," + "Label:" + (label!=EPSILON? label.ToString():"EPSILON")); if (!processedStates.Contains(dest.StateId)) { unprocessedStates.PushBack(dest); } } } } processedStates.Add(state.StateId); } } } } #endif _NFA = A; }
private void Push(Char input) { var state0 = new State(++_nextStateId); var state1 = new State(++_nextStateId); state0.AddTransition(input, state1); FiniteStateAutomaton fsa = new FiniteStateAutomaton(); fsa.PushBack(state0); fsa.PushBack(state1); _operandStack.Push(fsa); _inputSet.Add(input); }
private void ConvertNFAToDFA() { if (_NFA == null) return; if (_DFA == null) _DFA = new FiniteStateAutomaton(); _nextStateId = 0; Stack<State> unmarkedStates = new Stack<State>(); HashSet<State> DFAStartStateSet = new HashSet<State>(); HashSet<State> NFAStartStateSet = new HashSet<State>(); NFAStartStateSet.Add(_NFA.GetFirstState()); DFAStartStateSet = EpsilonClosure(NFAStartStateSet); var DFAStartState = new State(++_nextStateId, DFAStartStateSet); _DFA.PushBack(DFAStartState); unmarkedStates.Push(DFAStartState); while (unmarkedStates.Count > 0) { var processingDFAState = unmarkedStates.Pop(); State dest = null; foreach (var item in _inputSet) { var moveStates = Move(item, processingDFAState.NFAStatesSet); var epsilonClosureStats = EpsilonClosure(moveStates); bool found = false; foreach (var s in _DFA.GetStates()) { if (SameStatesSet(s.NFAStatesSet, epsilonClosureStats)) { found = true; dest = s; break; } } if (!found) { var newState = new State(++_nextStateId, epsilonClosureStats); unmarkedStates.Push(newState); _DFA.PushBack(newState); processingDFAState.AddTransition(item, newState); } else { processingDFAState.AddTransition(item, dest); } } } }