Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }