Sunteți pe pagina 1din 6

Program of NFA to DFA Conversion.

using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Threading.Tasks;

using System.Collections.Generic; namespace NfaToDfa { public class Exception : System.Exception { public Exception(string message) : base(message) { } } public class State { private bool _accepting; public bool Accepting { get { return _accepting; } set { _accepting = value; } } /** A small integer that uniquely identifies each state. */ private uint _id; public uint Id { get { return _id; } } private List<Transition> _targets = new List<Transition>(); public State(uint id) { _id = id; } /** Adds a target transition to this state. */ public void AddTarget(Transition target) { System.Diagnostics.Debug.Assert(_targets.IndexOf(target) == -1); _targets.Add(target); } protected static void DumpChildren(System.IO.TextWriter writer, string prefix, List<Transition> transitions) { if (transitions.Count < 1) return; writer.Write("{0} = [ {1}", prefix, transitions[0].Target.Id); for (int i = 1; i < transitions.Count; i += 1) { writer.Write(", {0}", transitions[i].Target.Id); } writer.Write(" ]"); } internal void DumpInternal(System.IO.TextWriter writer, Dictionary<State, bool> visited) { if (visited.ContainsKey(this)) return; visited[this] = true; writer.Write("{0,4} ", Id); DumpChildren(writer, "children", _targets); if (_accepting) { if (_targets.Count != 0) writer.Write(", "); writer.WriteLine("accepting"); } writer.WriteLine(); } public States Move(char value) { States result = new States();

foreach (Transition transition in _targets) { State found = transition.Move(value); if (found == null) continue; result.Add(found); } return result; } public States EpsilonClosure() { States result = new States(); result.Add(this); foreach (Transition transition in _targets) { if (transition is EpsilonTransition) { result.Add(transition.Target); // recursively find the epsilon closure of the found one States found = transition.Target.EpsilonClosure(); foreach (State item in found) { result.Add(item); } } } return result; } } public class States : List<State> { /** Sorted list variant of Add(). */ public new void Add(State value) { int i = 0; foreach (State state in this) { // ignore attempts to add duplicates if (state.Id == value.Id) return; if (state.Id > value.Id) break; i++; } Insert(i, value); } public new int IndexOf(State value) { int i = 0; foreach (State state in this) { if (state.Id == value.Id) return i; if (state.Id > value.Id) return -1; i++; } return -1; } public override string ToString() { System.Text.StringBuilder text = new System.Text.StringBuilder(); int i = 0; text.Append("{ "); foreach (State state in this) { if (i++ > 0) text.Append(", "); text.Append(state.Id.ToString()); } if (i > 0) text.Append(" "); text.Append("}");

return text.ToString(); } public States EpsilonClosure() { States result = new States(); foreach (State state in this) { States found = state.EpsilonClosure(); foreach (State item in found) { result.Add(item); } } return result; } public States Move(char value) { States result = new States(); foreach (State state in this) { States found = state.Move(value); foreach (State item in found) { result.Add(item); } } return result; } } /** A transition from one state to another state over some input character. */ public abstract class Transition { /** The source state of the transition; only used to make the output more readable. */ private State _source; public State Source { get { return _source; } } /** The target of this transition - the state that the transition leads to. */ private State _target; public State Target { get { return _target; } } /** Creates a new transition and adds the target state to the source state's list of outgoing transitions. */ public Transition(State source, State target) { System.Diagnostics.Debug.Assert(source != null); System.Diagnostics.Debug.Assert(target != null); _source = source; _target = target; source.AddTarget(this); } public abstract State Move(char value); public virtual void Dump(System.IO.TextWriter writer) { System.Console.WriteLine("{0,4} {0,4}", _source.Id, _target.Id); } } public class EpsilonTransition : Transition { public EpsilonTransition(State source, State target) : base(source, target) { } public override State Move(char value) { return null; } }

public class CharacterTransition : Transition { private char mValue; public char Value { get { return mValue; } } public CharacterTransition(State source, State target, char value) : base(source, target) { mValue = value; } public override State Move(char value) { if (mValue != value) return null; return Target; } } public class Nfa { private State[] _states = new State[0]; private List<Transition> _transitions = new List<Transition>(); private char _lower = char.MaxValue; public char Lower { get { return _lower; } } private char _upper = char.MinValue; public char Upper { get { return _upper; } } private int[,] _table = new int[0, 0]; public int[,] Table { get { return _table; } } private void GrowStates(uint size) { if (size <= _states.Length) return; State[] array = new State[size]; // copy states in _states for (uint i = 0; i < _states.Length; i++) array[i] = _states[i]; // create new states not in _states for (uint i = (uint)_states.Length; i < size; i++) array[i] = new State(i); _states = array; } public void AddEpsilonTransition(uint source, uint target) { GrowStates(System.Math.Max(source, target) + 1); _transitions.Add(new EpsilonTransition(_states[source], _states[target])); } public void AddCharacterTransition(uint source, uint target, char value) { GrowStates(System.Math.Max(source, target) + 1); // compute the bounds of the NFA if (value < _lower) _lower = value; if (value > _upper) _upper = value; _transitions.Add(new CharacterTransition(_states[source], _states[target], value)); }

public void Dump(System.IO.TextWriter writer) { for (int i = 0; i < _states.Length; i++) { States epsilons = _states[i].EpsilonClosure(); System.Console.WriteLine("EpsilonClosure(s[{0}]) = {1}", i, epsilons.ToString()); for (char ch = Lower; ch <= Upper; ch++) { States moves = epsilons.Move(ch); States epsimove = moves.EpsilonClosure(); System.Console.WriteLine("Move({0}, '{1}') = {2}", epsilons.ToString(), ch, moves.ToString()); System.Console.WriteLine("Epsilon({0}) = {1}", moves.ToString(), epsimove.ToString()); System.Console.WriteLine(); } } } public void SetAcceptingState(uint number) { _states[number].Accepting = true; }

public int[,] ConstructSubset() { Dictionary<string, int> symbols = new Dictionary<string, int>(); States q0 = _states[0].EpsilonClosure(); symbols[q0.ToString()] = symbols.Count; List<string> Q = new List<string>(); Q.Add(q0.ToString()); List<States> worklist = new List<States>(); worklist.Add(q0); int x0 = 0; int y0 = (int)Upper - (int)Lower + 1; _table = new int[x0, y0]; while (worklist.Count > 0) { States q = worklist[0]; worklist.RemoveAt(0); if (!symbols.ContainsKey(q.ToString())) symbols[q.ToString()] = symbols.Count; for (char ch = Lower; ch <= Upper; ch++) { States t = q.Move(ch).EpsilonClosure(); if (!symbols.ContainsKey(t.ToString())) symbols[t.ToString()] = symbols.Count; // _table[x, y] = z int x = symbols[q.ToString()]; int y = (int)(ch - Lower); int z = symbols[t.ToString()]; // resize the transition table in steps of 128 states at a time if (x >= _table.GetLength(0)) { int[,] array = new int[x + 128, _table.GetLength(1)]; for (int i = 0; i < x; i++) for (int j = 0; j < y0; j++) array[i, j] = _table[i, j]; _table = array; } // assign the computed value _table[x, y] = z; x0 = System.Math.Max(x0, x + 1); if (Q.IndexOf(t.ToString()) == -1) { Q.Add(t.ToString()); worklist.Add(t); } } } // shrink the table to match the actual size int[,] result = new int[x0, y0];

for (int i = 0; i < x0; i++) for (int j = 0; j < y0; j++) result[i, j] = _table[i, j]; _table = result; return _table; } } public class Program { public static int Main(string[] args) { // create the NFA var nfa = new Nfa(); nfa.AddEpsilonTransition(0, 1); nfa.AddEpsilonTransition(0, 7); nfa.AddEpsilonTransition(1, 2); nfa.AddEpsilonTransition(1, 4); nfa.AddCharacterTransition(2, 3, 'a'); nfa.AddEpsilonTransition(3, 6); nfa.AddCharacterTransition(4, 5, 'b'); nfa.AddEpsilonTransition(5, 6); nfa.AddEpsilonTransition(6, 1); nfa.AddEpsilonTransition(6, 7); nfa.AddCharacterTransition(7, 8, 'a'); nfa.AddCharacterTransition(8, 9, 'b'); nfa.AddCharacterTransition(9, 10, 'b'); nfa.SetAcceptingState(10); System.Console.WriteLine("Charset = {0}..{1}", nfa.Lower, nfa.Upper); nfa.Dump(System.Console.Out); // compute the transition table int[,] table = nfa.ConstructSubset(); System.Console.Write("\\ "); for (char ch = nfa.Lower; ch <= nfa.Upper; ch++) System.Console.Write("{0} ", ch); System.Console.WriteLine(); for (uint row = 0; row < table.GetLength(0); row++) { System.Console.Write("{0} ", row); for (uint col = 0; col < table.GetLength(1); col++) { System.Console.Write("{0} ", table[row, col]); } System.Console.WriteLine(); } return 0; } } }

S-ar putea să vă placă și