/// <summary> /// Creates an automaton that repeats the sub-automaton a number of times in the given range [min, max] /// </summary> /// <param name="sub">The sub-automaton</param> /// <param name="min">The minimum (included) number of time to repeat</param> /// <param name="max">The maximum (included) number of time to repeat</param> /// <returns>The new automaton</returns> // TODO: should get rid of static methods public static NFA NewRepeatRange(NFA sub, int min, int max) { NFA final = NewMinimal(); NFAState last = final.StateEntry; for (int i = 0; i != min; i++) { NFA inner = sub.Clone(); final.states.AddRange(inner.states); last.AddTransition(NFA.EPSILON, inner.StateEntry); last = inner.StateExit; } for (int i = min; i != max; i++) { NFA inner = NewOptional(sub, true); final.states.AddRange(inner.states); last.AddTransition(NFA.EPSILON, inner.StateEntry); last = inner.StateExit; } last.AddTransition(NFA.EPSILON, final.StateExit); if (min == 0) { final.StateEntry.AddTransition(NFA.EPSILON, final.StateExit); } return(final); }
/// <summary> /// Creates an automaton that repeats the sub-automaton one or more times /// </summary> /// <param name="sub">The sub-automaton</param> /// <param name="useClones">True to completely clone the sub-automaton</param> /// <returns>The new automaton</returns> // TODO: should get rid of static methods public static NFA NewRepeatOneOrMore(NFA sub, bool useClones) { NFA final = NewMinimal(); if (useClones) { sub = sub.Clone(); } final.states.AddRange(sub.states); final.StateEntry.AddTransition(NFA.EPSILON, sub.StateEntry); sub.StateExit.AddTransition(NFA.EPSILON, final.StateExit); final.StateExit.AddTransition(NFA.EPSILON, sub.StateEntry); return(final); }
/// <summary> /// Creates an automaton that concatenates the two sub-automaton /// </summary> /// <param name="left">The left automaton</param> /// <param name="right">The right automaton</param> /// <param name="useClones">True to completely clone the sub-automata</param> /// <returns>The new automaton</returns> // TODO: should get rid of static methods public static NFA NewConcatenation(NFA left, NFA right, bool useClones) { NFA final = new NFA(); if (useClones) { left = left.Clone(true); right = right.Clone(true); } final.states.AddRange(left.states); final.states.AddRange(right.states); final.StateEntry = left.StateEntry; final.StateExit = right.StateExit; left.StateExit.AddTransition(NFA.EPSILON, right.StateEntry); return(final); }
/// <summary> /// Creates an automaton that is the union of the two sub-automaton /// </summary> /// <param name="left">The left automaton</param> /// <param name="right">The right automaton</param> /// <param name="useClones">True to completely clone the sub-automata</param> /// <returns>The new automaton</returns> // TODO: should get rid of static methods public static NFA NewUnion(NFA left, NFA right, bool useClones) { NFA final = NewMinimal(); if (useClones) { left = left.Clone(true); right = right.Clone(true); } final.states.AddRange(left.states); final.states.AddRange(right.states); final.StateEntry.AddTransition(NFA.EPSILON, left.StateEntry); final.StateEntry.AddTransition(NFA.EPSILON, right.StateEntry); left.StateExit.AddTransition(NFA.EPSILON, final.StateExit); right.StateExit.AddTransition(NFA.EPSILON, final.StateExit); return(final); }
/// <summary> /// Creates an automaton that is the difference between the left and right sub-automata /// </summary> /// <param name="left">The left automaton</param> /// <param name="right">The right automaton</param> /// <param name="useClones">True to completely clone the sub-automata</param> /// <returns>The new automaton</returns> // TODO: should get rid of static methods public static NFA NewDifference(NFA left, NFA right, bool useClones) { NFA final = NewMinimal(); NFAState statePositive = final.AddNewState(); NFAState stateNegative = final.AddNewState(); statePositive.Mark = 1; stateNegative.Mark = -1; if (useClones) { left = left.Clone(true); right = right.Clone(true); } final.states.AddRange(left.states); final.states.AddRange(right.states); final.StateEntry.AddTransition(NFA.EPSILON, left.StateEntry); final.StateEntry.AddTransition(NFA.EPSILON, right.StateEntry); left.StateExit.AddTransition(NFA.EPSILON, statePositive); right.StateExit.AddTransition(NFA.EPSILON, stateNegative); statePositive.AddTransition(NFA.EPSILON, final.StateExit); final.StateExit.AddItem(DummyItem.Instance); DFA equivalent = new DFA(final); equivalent.Prune(); final = new NFA(equivalent); final.StateExit = final.AddNewState(); foreach (NFAState state in final.states) { if (state.Items.Contains(DummyItem.Instance)) { state.ClearItems(); state.AddTransition(NFA.EPSILON, final.StateExit); } } return(final); }