/// <summary> /// Creates an alternation between this NFA and the given NFA /// </summary> /// <param name="secondNFA">NFA being alternated with this NFA</param> public void Alternation(NFA secondNFA) { // alternating NFAs requires we make a new start state that has epsilon transitions to // both of the given NFAs // create new start state (not accepting) State newStart = new State(false); // add epsilon transitions from the new start to the start of the two original NFAs newStart.AddTransition(Transition.Epsilon, this.GetStart()); newStart.AddTransition(Transition.Epsilon, secondNFA.GetStart()); // make the start of this NFA the new start state this.SetStart(newStart); }
/// <summary> /// Concatenates the given NFA to the end of this NFA /// </summary> /// <param name="appendingNFA">NFA being appended to the end of this NFA</param> public void Concatenate(NFA appendingNFA) { // when concatenating two NFAs, accepting states of the first NFA // are given epsilon transitions to the start state of the seconds NFA // keep a list of visited states so we don't add states over and over List <State> visited = new List <State>(); // reference to the current state we're working with State curState; // queue of states to be checked Queue <State> stateQueue = new Queue <State>(); stateQueue.Enqueue(this.GetStart()); // while states exist in the queue, continue to loop while (stateQueue.Count > 0) { curState = stateQueue.Dequeue(); if (visited.Contains(curState)) { continue; } // add this state to the list of visited states visited.Add(curState); // queue up all states that can be transitioned to foreach (Transition t in curState.GetTransitions()) { stateQueue.Enqueue(t.GetState()); } // if this state is accepting, add an epsilon transition to the start of // the appendingNFA if (curState.IsAccepting()) { curState.AddTransition(Transition.Epsilon, appendingNFA.GetStart()); // this state is no longer accepting curState.SetAccepting(false); } } }