public static NFA Or(NFA a, NFA b) { NFA nfa = new NFA(); // Composite NFA contains all the and all edges in both NFAs nfa.AddAll(a); nfa.AddAll(b); // Add a start state, link to both NFAs old start state with // epsilon links nfa.StartState = new NFA.State(); nfa.States.Add(nfa.StartState); nfa.Transitions.Add(new Transition <NFA.State>(nfa.StartState, a.StartState)); nfa.Transitions.Add(new Transition <NFA.State>(nfa.StartState, b.StartState)); // Add a new accept state, link all old accept states to the new accept // state with an epsilon link and remove the accept flag NFA.State newAcceptState = new NFA.State { AcceptState = true }; foreach (NFA.State oldAcceptState in nfa.States.Where(f => f.AcceptState)) { oldAcceptState.AcceptState = false; nfa.Transitions.Add(new Transition <NFA.State>(oldAcceptState, newAcceptState)); } nfa.States.Add(newAcceptState); return(nfa); }
public static NFA RepeatZeroOrMore(NFA input) { NFA nfa = new NFA(); // Add everything from the input nfa.AddAll(input); // Create a new starting state, link it to the old accept state with Epsilon nfa.StartState = new NFA.State(); nfa.States.Add(nfa.StartState); NFA.State oldAcceptState = input.States.First(f => f.AcceptState); nfa.Transitions.Add(new Transition <NFA.State>(nfa.StartState, oldAcceptState)); // Add epsilon link from old accept state of input to start, to allow for repetition nfa.Transitions.Add(new Transition <NFA.State>(oldAcceptState, input.StartState)); // Create new accept state, link old accept state to new accept state with epsilon NFA.State acceptState = new NFA.State { AcceptState = true }; nfa.States.Add(acceptState); oldAcceptState.AcceptState = false; nfa.Transitions.Add(new Transition <NFA.State>(oldAcceptState, acceptState)); return(nfa); }
private static NFA NumberedRepeat(NFA nfa, int minRepetitions, int maxRepetitions) { // To create a suitable expression, the special case of infinite max repetitions // must be separately handled. bool infiniteMax = false; if (maxRepetitions == int.MaxValue) { infiniteMax = true; maxRepetitions = minRepetitions; } else if (maxRepetitions < minRepetitions) { maxRepetitions = minRepetitions; } // Copy the NFA max repetitions times, link them together. NFA output = nfa.Copy(); Stack <NFA.State> epsilonLinkStates = new Stack <NFA.State>(); for (int i = 1; i < maxRepetitions; ++i) { NFA newNfa = nfa.Copy(); if (i >= minRepetitions || (infiniteMax && i == maxRepetitions - 1)) { epsilonLinkStates.Push(newNfa.StartState); } output = And(output, newNfa); } if (infiniteMax) { // Use Single to force an exception if this has gone astray NFA.State finalState = epsilonLinkStates.Single(); // Make a little epsilon loop from the final accept state to the start state of the final state output.Transitions.Add(new Transition <NFA.State>(output.States.Single(f => f.AcceptState), finalState)); } else { // Add epsilon transitions from accept to beginning states of NFAs in the chain NFA.State acceptState = output.States.Single(f => f.AcceptState); while (epsilonLinkStates.Count > 0) { output.Transitions.Add(new Transition <NFA.State>(epsilonLinkStates.Pop(), acceptState)); } } return(output); }
private static NFA RepeatOnceOrMore(NFA nfa) { // Add an epsilon transition from the accept state back to the start state NFA.State oldAcceptState = nfa.States.First(f => f.AcceptState); nfa.Transitions.Add(new Transition <NFA.State>(oldAcceptState, nfa.StartState)); // Add a new accept state, since we cannot have edges exiting the accept state NFA.State newAcceptState = new NFA.State { AcceptState = true }; nfa.Transitions.Add(new Transition <NFA.State>(oldAcceptState, newAcceptState)); nfa.States.Add(newAcceptState); // Clear the accept flag of the old accept state oldAcceptState.AcceptState = false; return(nfa); }
private static NFA Accept(CharSet acceptCharacters) { // Generate a NFA with a simple path with one state transitioning into an accept state. NFA nfa = new NFA(); NFA.State state = new NFA.State(); nfa.States.Add(state); NFA.State acceptState = new NFA.State { AcceptState = true }; nfa.States.Add(acceptState); nfa.Transitions.Add(new Transition <NFA.State>(state, acceptState, acceptCharacters)); nfa.StartState = state; return(nfa); }