/// <summary> /// Initializes a DFA and generates all the states and transitions given a NFA /// </summary> /// <param name="nfa">NFA from which the DFA will be populated</param> public DFA(NFA <T> nfa) : base() { List <T> symbols = nfa.Symbols; this.BuildSubset(nfa, nfa.InitialState); }
/// <summary> /// Performs the concatenation of two NFA's /// </summary> /// <param name="nfa">NFA to be concatenated</param> /// <returns>The concatenated NFA</returns> public NFA <T> And(NFA <T> nfa) { NFA <T> result = this.Clone() as NFA <T>; NFA <T> andparcel = nfa.Clone() as NFA <T>; int nextavail = result.NextAvailableState; andparcel.OffsetStates(nextavail - 1); result.Transitions.AddRange(andparcel.Transitions); result.AcceptingStates.Clear(); result.AcceptingStates.AddRange(andparcel.AcceptingStates); return(result); }
/// <summary> /// Performs the alternation of two NFA's /// </summary> /// <param name="nfa">NFA to be alternation</param> /// <returns>The alternation NFA</returns> public NFA <T> Or(NFA <T> nfa) { NFA <T> result = this.Clone() as NFA <T>; NFA <T> orparcel = nfa.Clone() as NFA <T>; int nextavail = result.NextAvailableState; //first state will be reconverted (avoid state number loss) orparcel.OffsetStates(nextavail - 1); orparcel.RenumberState(orparcel.InitialState, result.InitialState); orparcel.RenumberState(orparcel.AcceptingStates[0], result.AcceptingStates[0]); result.Transitions.AddRange(orparcel.Transitions); return(result); }
/// <summary> /// Performs the kleene/star operation of the NFA /// </summary> /// <returns>The kleene/star NFA</returns> public NFA <T> Kleene() { NFA <T> result = this.Clone() as NFA <T>; result.OffsetStates(1); int nextavail = result.NextAvailableState; result.Transitions.Add(new Transition <T>(0, this.Epsilon, 1)); result.Transitions.Add(new Transition <T>(result.AcceptingStates[0], this.Epsilon, nextavail)); result.Transitions.Add(new Transition <T>(nextavail, this.Epsilon, 1)); result.Transitions.Add(new Transition <T>(0, this.Epsilon, nextavail)); result.AcceptingStates.Clear(); result.AcceptingStates.Add(nextavail); result.InitialState = 0; return(result); }
/// <summary> /// Implementation of the IClonable interface /// </summary> /// <returns>Returns a clone of the NFA object</returns> public object Clone() { NFA <T> result = new NFA <T>(this.Epsilon); result.Transitions.Clear(); foreach (Transition <T> t in this.Transitions) { Transition <T> clonet = new Transition <T>(t.PreviousState, t.Symbol, t.NextState); if (!result.Transitions.Contains(clonet)) { result.Transitions.Add(new Transition <T>(t.PreviousState, t.Symbol, t.NextState)); } } result.AcceptingStates.AddRange(this.AcceptingStates.ToArray()); result.InitialState = this.InitialState; return(result); }
/// <summary> /// Performs the replacement of all Transitions given a symbol by a full NFA /// </summary> /// <param name="symbol">Generic type T value of the trigger to be replaced</param> /// <param name="replacement">The NFA be inserted</param> /// <returns>A NFA with all the replacemente in place</returns> public NFA <T> ReplaceTransitions(T symbol, NFA <T> replacement) { NFA <T> result = this.Clone() as NFA <T>; for (int i = 0; i < result.Transitions.Count; i++) { if (result.Transitions[i].Symbol.CompareTo(symbol) == 0) { NFA <T> insert = replacement.Clone() as NFA <T>; insert.OffsetStates(result.NextAvailableState); insert.RenumberState(insert.InitialState, result.Transitions[i].PreviousState); insert.RenumberState(insert.AcceptingStates[0], result.Transitions[i].NextState); result.Transitions.AddRange(insert.Transitions); result.Transitions.RemoveAt(i); i--; } } return(result); }
/// <summary> /// Performs the NFA to DFA convertion (recursive) /// </summary> /// <param name="nfa">The NFA object to convert</param> /// <param name="start">The strting state</param> private void BuildSubset(NFA <T> nfa, int start) { Stack <List <int> > unprocessedSubsets = new Stack <List <int> >(); int availableState = 0; List <int> startPoint = nfa.EpsilonClosure(start); unprocessedSubsets.Push(startPoint); _SubSets[startPoint] = availableState++; if (startPoint.Contains(nfa.AcceptingStates[0]) && !this.AcceptingStates.Contains(_SubSets[startPoint])) { this.AcceptingStates.Add(_SubSets[startPoint]); } while (unprocessedSubsets.Count > 0) { List <int> subset = unprocessedSubsets.Pop(); for (int i = 0; i < subset.Count; i++) { foreach (T symbol in nfa.Symbols) { int nextstate = nfa.GetNextState(subset[i], symbol); if (nextstate >= 0) { List <int> newsubset = nfa.EpsilonClosure(nextstate); if (!_SubSets.ContainsKey(newsubset)) { unprocessedSubsets.Push(newsubset); _SubSets[newsubset] = availableState++; } this.Transitions.Add(new Transition <T>(_SubSets[subset], symbol, _SubSets[newsubset])); if (newsubset.Contains(nfa.AcceptingStates[0]) && !this.AcceptingStates.Contains(_SubSets[newsubset])) { this.AcceptingStates.Add(_SubSets[newsubset]); } } } } } }