public ail.net.parser.Fsa Minimize(ail.net.parser.Fsa.EMinimizationMode xi_mode) { ail.net.parser.Fsa result = new ail.net.parser.Fsa(); // phase I (clean) RemoveUselessStates(); // phase II (divide fsa into equivalent groups, each group will be new fsa state) Hashtable partition = new Hashtable(); BuildPartition(ref partition, xi_mode); // phase III (compose fsa) foreach (ail.net.parser.FsaStateSet group in partition.Values) { ail.net.parser.FsaState new_state = result.AddState(group.Id); ail.net.parser.FsaState old_state = (ail.net.parser.FsaState)ail.net.framework.Functor.FirstElementOfCollection(group.States.Values); // check if group has start state foreach (ail.net.parser.FsaState state in group.States.Values) { if (IsStartState(state)) { result.StartState = new_state; break; } } // check if group final state foreach (ail.net.parser.FsaState state in group.States.Values) { if (IsFinalState(state)) { result.AddFinalState(new_state, state.Token); break; } } // add transitions foreach (ail.net.parser.FsaTransition transition in old_state.Transitions.Values) { ail.net.parser.FsaStateSet transition_group = GetGroupFromState(transition.End, partition); ail.net.framework.Assert.NonNullReference(transition_group, "transition_group"); result.AddTransition(new_state.Id, transition_group.Id, transition.Predicate.Text, transition.Predicate.SwitchChar, transition.Predicate.Context, transition.Predicate.Rank); } } // phase IV (clean) result.RemoveUselessStates(); return(result); }
public static void TestFsa() { try { /* * ail.net.parser.Fsa fsa = new ail.net.parser.Fsa(); * * ail.net.parser.FsaState q0 = fsa.AddState(); * q0.Label = q0.Id.ToString(); * ail.net.parser.FsaState q1 = fsa.AddState(); * q1.Label = q1.Id.ToString(); * ail.net.parser.FsaState q2 = fsa.AddState(); * q2.Label = q2.Id.ToString(); * ail.net.parser.FsaState q3 = fsa.AddState(); * q3.Label = q3.Id.ToString(); * ail.net.parser.FsaState q4 = fsa.AddState(); * q4.Label = q4.Id.ToString(); * ail.net.parser.FsaState q5 = fsa.AddState(); * q5.Label = q5.Id.ToString(); * ail.net.parser.FsaState q6 = fsa.AddState(); * q6.Label = q6.Id.ToString(); * ail.net.parser.FsaState q7 = fsa.AddState(); * q7.Label = q7.Id.ToString(); * ail.net.parser.FsaState q8 = fsa.AddState(); * q8.Label = q8.Id.ToString(); * ail.net.parser.FsaState q9 = fsa.AddState(); * q9.Label = q9.Id.ToString(); * ail.net.parser.FsaState q10 = fsa.AddState(); * q10.Label = q10.Id.ToString(); * ail.net.parser.FsaState q11 = fsa.AddState(); * q11.Label = q11.Id.ToString(); * ail.net.parser.FsaState q12 = fsa.AddState(); * q12.Label = q12.Id.ToString(); * ail.net.parser.FsaState q13 = fsa.AddState(); * q13.Label = q13.Id.ToString(); * ail.net.parser.FsaState q14 = fsa.AddState(); * q14.Label = q14.Id.ToString(); * * fsa.AddTransition(q0, q1, "IsCharLowerCaseI"); * fsa.AddTransition(q1, q2, "IsCharLowerCaseF"); * * fsa.AddTransition(q0, q3, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q3, q4, "IsCharLowerCaseA"); * fsa.AddTransition(q4, q7, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q7, q5, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q5, q6, "IsCharLowerCaseA"); * fsa.AddTransition(q5, q6, "IsCharDecimalZero"); * fsa.AddTransition(q6, q7, ail.net.parser.FsaTransition.kEpsilonPredicate); * * fsa.AddTransition(q0, q8, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q8, q9, "IsCharDecimalZero"); * fsa.AddTransition(q9, q12, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q12, q10, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q10, q11, "IsCharDecimalZero"); * fsa.AddTransition(q11, q12, ail.net.parser.FsaTransition.kEpsilonPredicate); * * fsa.AddTransition(q0, q13, ail.net.parser.FsaTransition.kEpsilonPredicate); * fsa.AddTransition(q13, q14, "IsWhiteSpaceChar"); * * // fsa.AddFinalState(q2, (int)ail.net.parser.ReToken.EType.eBar); * // fsa.AddFinalState(q7, (int)ail.net.parser.ReToken.EType.eChar); * // fsa.AddFinalState(q12, (int)ail.net.parser.ReToken.EType.eInteger); * // fsa.AddFinalState(q14, (int)ail.net.parser.ReToken.EType.eHexChar); * * // fsa.Print(); */ /* * foreach(ail.net.parser.FsaState state in fsa.States.Values) * { * ail.net.parser.FsaStateSet eclosure = fsa.CalculateStateEclosure(state); * * if(eclosure.States.Count > 0) * { * Console.WriteLine("state: {0}", state.Id); * eclosure.Print(); * Console.WriteLine(""); * * ail.net.parser.FsaStateSet move = fsa.CalculateMove(eclosure, "IsCharLowerCaseA"); * * if(move.States.Count > 0) * { * Console.WriteLine("state: {0}", state.Id); * move.Print(); * Console.WriteLine(""); * } * } * } */ // ail.net.parser.Fsa nfa = fsa.Nfa2Dfa(); // nfa.Print(); { // aho ail.net.parser.Fsa dfa = new ail.net.parser.Fsa(); ail.net.parser.FsaState q0 = dfa.AddState(); q0.Label = "A"; ail.net.parser.FsaState q1 = dfa.AddState(); q1.Label = "B"; ail.net.parser.FsaState q2 = dfa.AddState(); q2.Label = "C"; ail.net.parser.FsaState q3 = dfa.AddState(); q3.Label = "D"; ail.net.parser.FsaState q4 = dfa.AddState(); q4.Label = "E"; dfa.AddTransition(q0, q1, "a"); dfa.AddTransition(q0, q2, "b"); dfa.AddTransition(q1, q1, "a"); dfa.AddTransition(q1, q3, "b"); dfa.AddTransition(q2, q2, "b"); dfa.AddTransition(q2, q1, "a"); dfa.AddTransition(q3, q1, "a"); dfa.AddTransition(q3, q4, "b"); dfa.AddTransition(q4, q1, "a"); dfa.AddTransition(q4, q2, "b"); dfa.AddFinalState(q4, new ail.net.parser.CppToken((int)ail.net.parser.CppToken.EType.eIdentifier, 0)); // ail.net.parser.Fsa mfa = dfa.Minimize(ail.net.parser.Fsa.EMinimizationMode.eTable); } { // minimize_dfa.pdf ail.net.parser.Fsa dfa = new ail.net.parser.Fsa(); ail.net.parser.FsaState q0 = dfa.AddState(); q0.Label = "A"; ail.net.parser.FsaState q1 = dfa.AddState(); q1.Label = "B"; ail.net.parser.FsaState q2 = dfa.AddState(); q2.Label = "C"; // ail.net.parser.FsaState q3 = dfa.AddState(); // q3.Label = "D"; ail.net.parser.FsaState q4 = dfa.AddState(); q4.Label = "E"; ail.net.parser.FsaState q5 = dfa.AddState(); q5.Label = "F"; ail.net.parser.FsaState q6 = dfa.AddState(); q6.Label = "G"; ail.net.parser.FsaState q7 = dfa.AddState(); q7.Label = "H"; dfa.AddTransition(q0, q1, "0"); dfa.AddTransition(q0, q5, "1"); dfa.AddTransition(q1, q6, "0"); dfa.AddTransition(q1, q2, "1"); dfa.AddTransition(q2, q0, "0"); dfa.AddTransition(q2, q2, "1"); // dfa.AddTransition(q3, q2, "0"); // dfa.AddTransition(q3, q6, "1"); dfa.AddTransition(q4, q7, "0"); dfa.AddTransition(q4, q5, "1"); dfa.AddTransition(q5, q2, "0"); dfa.AddTransition(q5, q6, "1"); dfa.AddTransition(q6, q6, "0"); dfa.AddTransition(q6, q4, "1"); dfa.AddTransition(q7, q6, "0"); dfa.AddTransition(q7, q2, "1"); dfa.AddFinalState(q2, new ail.net.parser.CppToken((int)ail.net.parser.CppToken.EType.eIdentifier, 0)); ail.net.parser.Fsa mfa = dfa.Minimize(ail.net.parser.Fsa.EMinimizationMode.ePartition); Console.WriteLine(mfa.States.Count); } } catch (Exception ex) { string m = ex.Message; } }
public ail.net.parser.Fsa Nfa2Dfa() { // Conversion of an NFA into a DFA (subset construction) // ..................................................... // Input: An NFA N. // Output: A DFA D accepting the same language. // Operations: // e-closure(s) is the set of NFA states reachable from s on e-transitions alone. // e-closure(T) is the union of e-closure(r) for all r in T. // move(T, a) is the set of NFA states to which there is a transition on input a from some NFA state in T. // // set the start state to e-closure(s0) and unmark it. // While there is an unmarked state T in Dstates do // Mark T // For each input symbol a do // If U := e-closure(move(T, a)); // If U is not in Dstates then // Add U as an unmarked state to Dstates; // Dtran(T, a) := U; // End; // End; ail.net.parser.Fsa result = new ail.net.parser.Fsa(); ArrayList dfa_states = new ArrayList(); // build pseudo dfa ail.net.parser.FsaStateSet start_dfa_state = CalculateStateEclosure(StartState); start_dfa_state.Id = dfa_states.Count; start_dfa_state.Marked = false; dfa_states.Add(start_dfa_state); bool proceed = false; for (;;) { IEnumerator dfa_state_enum = dfa_states.GetEnumerator(); while (dfa_state_enum.MoveNext()) { ail.net.parser.FsaStateSet dfa_state = (ail.net.parser.FsaStateSet)dfa_state_enum.Current; if (!dfa_state.Marked) { dfa_state.Marked = true; foreach (ail.net.parser.FsaTransitionPredicate predicate in Predicates.Values) { if (predicate.Text != ail.net.parser.FsaTransition.kEpsilonPredicate) { ail.net.parser.FsaStateSet move_set = CalculateMove(dfa_state, predicate.Text); if (move_set != (object)null) { ail.net.parser.FsaStateSet pseudo_dfa_state = CalculateEClosureFromMove(move_set); if (pseudo_dfa_state != (object)null && pseudo_dfa_state.States.Count > 0) { ail.net.parser.FsaStateSet new_dfa_state = HasDfaCompoundState(dfa_states, pseudo_dfa_state); if (new_dfa_state == (object)null) { new_dfa_state = pseudo_dfa_state; new_dfa_state.Id = dfa_states.Count; new_dfa_state.Marked = false; dfa_states.Add(new_dfa_state); dfa_state_enum = dfa_states.GetEnumerator(); // reset iterator } if (!dfa_state.Transitions.Contains(dfa_state.Transitions.Count)) { ail.net.parser.FsaTransition transition = new ail.net.parser.FsaTransition(dfa_state.Transitions.Count, dfa_state.Id, new_dfa_state.Id, predicate.Text, predicate.SwitchChar, predicate.Context, predicate.Rank); dfa_state.Transitions.Add(transition.Id, transition); } } } } } proceed = true; } } if (!proceed) { break; } proceed = false; } // populate states and final states foreach (ail.net.parser.FsaStateSet dfa_state in dfa_states) { ail.net.parser.FsaState state = result.AddState(dfa_state.Id); ail.net.framework.Assert.NonNullReference(state, "state"); foreach (ail.net.parser.FsaTransition transition in dfa_state.Transitions.Values) { result.AddTransition(transition.Start, transition.End, transition.Predicate.Text, transition.Predicate.SwitchChar, transition.Predicate.Context, transition.Predicate.Rank); } ail.net.parser.FsaState final_state = null; foreach (ail.net.parser.FsaState tmp_state in dfa_state.States.Values) { if (FinalStates.Contains(tmp_state.Id)) { ail.net.parser.FsaState org_state = (ail.net.parser.FsaState)States[tmp_state.Id]; ail.net.framework.Assert.NonNullReference(org_state, "org_state"); if (final_state == (object)null || org_state.Token.Priority > final_state.Token.Priority) { final_state = org_state; } } } if (final_state != (object)null) { result.AddFinalState(state, final_state.Token); } } result.StateCounter.Reset(States.Count); return(result); }
public void AddToken(ail.net.parser.Fsa xi_fsa, string xi_token, int xi_token_type, int xi_escape_token_type, string xi_escape_predicate) { ail.net.framework.Assert.NonNullReference(xi_fsa, "xi_fsa"); ail.net.framework.Assert.NonEmptyString(xi_token, "xi_token"); ail.net.parser.FsaState q1 = null; if (xi_fsa.StartState != (object)null) { q1 = xi_fsa.AddState(); xi_fsa.AddTransition(xi_fsa.StartState, q1, ail.net.parser.FsaTransition.kEpsilonPredicate); } else { q1 = xi_fsa.AddState(); } ail.net.parser.FsaState eq = null; // escape state if (xi_escape_token_type != ail.net.parser.Token.kUndefinedEscapeTokenType) { eq = xi_fsa.AddState(); xi_fsa.AddTransition(eq, eq, xi_escape_predicate, ail.net.parser.FsaTransition.kMaxRankValue); ail.net.parser.Token token = (ail.net.parser.Token)Factory.Create(Token.GetType()); token.Type = xi_escape_token_type; token.Priority = ail.net.parser.LexAnalyzer.kEscapeTokenPriority; xi_fsa.AddFinalState(eq, token); } ail.net.parser.FsaState q_prev = q1; ail.net.parser.FsaState q_curr = q1; for (int i = 0; i < xi_token.Length; i++) { q_curr = xi_fsa.AddState(); ail.net.framework.Assert.NonNullReference(q_curr, "q_curr"); xi_fsa.AddTransition(q_prev, q_curr, ail.net.framework.CharPredicate.BuildAsciiCharPredicate(xi_token[i]), (char)xi_token[i]); if (i == xi_token.Length - 1) { ail.net.parser.Token token = (ail.net.parser.Token)Factory.Create(Token.GetType()); token.Type = xi_token_type; token.Priority = ail.net.parser.LexAnalyzer.kDefaultTokenPriority; xi_fsa.AddFinalState(q_curr, token); } else if (xi_escape_token_type != ail.net.parser.Token.kUndefinedEscapeTokenType) { ail.net.parser.Token token = (ail.net.parser.Token)Factory.Create(Token.GetType()); token.Type = xi_escape_token_type; token.Priority = ail.net.parser.LexAnalyzer.kEscapeTokenPriority; xi_fsa.AddFinalState(q_curr, token); } if (xi_escape_token_type != ail.net.parser.Token.kUndefinedEscapeTokenType) { xi_fsa.AddTransition(q_curr, eq, xi_escape_predicate, ail.net.parser.FsaTransition.kMaxRankValue); } q_prev = q_curr; } }