private Hashtable SplitGroup(ail.net.parser.FsaStateSet xi_group, Hashtable xi_partition) { ail.net.framework.Assert.NonNullReference(xi_group, "xi_group"); ail.net.framework.Assert.Condition(xi_group.States.Count > 0, "xi_group.States.Count > 0"); ail.net.framework.Assert.NonNullReference(xi_partition, "xi_partition"); Hashtable result = new Hashtable(); // first state introduces new subgroup ail.net.parser.FsaStateSet group = new ail.net.parser.FsaStateSet(GroupCounter.Next()); result.Add(group.Id, group); group.States.Add(((ail.net.parser.FsaState)ail.net.framework.Functor.FirstElementOfCollection(xi_group.States.Values)).Id, (ail.net.parser.FsaState)ail.net.framework.Functor.FirstElementOfCollection(xi_group.States.Values)); // go over states in the group foreach (ail.net.parser.FsaState state in xi_group.States.Values) { bool added = false; // check if state is not ortogonal to any subgroup foreach (ail.net.parser.FsaStateSet subgroup in result.Values) { if (subgroup.States.Contains(state.Id)) // state == state { added = true; break; } ail.net.parser.FsaState group_state = (ail.net.parser.FsaState)ail.net.framework.Functor.FirstElementOfCollection(subgroup.States.Values); if (AreEqual(state, group_state, xi_partition)) { subgroup.States.Add(state.Id, state); added = true; break; } } // if state is ortogonal introduce a new group and add state to this new group if (!added) { group = new ail.net.parser.FsaStateSet(GroupCounter.Next()); result.Add(group.Id, group); group.States.Add(state.Id, state); } } return(result); }
private void BuildTable(ref Hashtable xio_partition) { //!! not implemented due to huge tables being built, postponed :( // Mark the distinguishable pairs of states. // To achieve this task, we first mark all pairs (p,q), where p belongs to F and // q does not belong to F as distinguishable. Then, we proceed as follows: // repeat // for all non-marked pairs {p,q} do // for each letter 'a' do // if the pair {(s)igma(p,a), (s)igma(q,a)} is marked // then mark {p,q} // until no new pairs are marked ail.net.framework.Assert.NonNullReference(xio_partition, "xio_partition"); // initialization, this algorithm is sensitive to states organization ResetMarkedStates(); xio_partition.Clear(); // table for 'A B C D E' states, cells in use marked with '*' // 0 A // 1 B * // 2 C * * // 3 D * * * // 4 E * * * * // A B C D E // 0 1 2 3 4 // access by (p, q) = table[ArithmeticProgressionSum(Math.Max(0, p_id-1)+q_id] // map[index][state] ArrayList map = new ArrayList(States.Values); Hashtable table = new Hashtable(CalculateTableSize()); // create table of pairs, also mark all pairs of accept and non-accept states as non-equivalent // keep only one of pairs (p, q) or (q, p) ArrayList states = new ArrayList(States.Values); states.Sort(); // states must be numbered in sequence for (int i = 0; i < states.Count - 1; i++) { for (int j = i + 1; j < states.Count; j++) { ail.net.parser.FsaState p_state = (ail.net.parser.FsaState)states[i]; ail.net.parser.FsaState q_state = (ail.net.parser.FsaState)states[j]; ail.net.parser.FsaPair pair = new ail.net.parser.FsaPair(p_state, q_state); table.Add(new ail.net.parser.FsaPairKey(p_state, q_state), pair); bool p_final = IsFinalState(p_state); bool q_final = IsFinalState(q_state); bool mark = ((p_final && !q_final) || (!p_final && q_final)); if (!mark && p_final && q_final) { mark = p_state.Token.Type != q_state.Token.Type; } if (mark) { pair.Marked = true; } } } // populate table for (;;) { bool process = false; foreach (ail.net.parser.FsaPair pair in table.Values) { if (!pair.Marked) { Hashtable predicates = CombinePredicates(pair.PState, pair.QState); foreach (ail.net.parser.FsaTransitionPredicate predicate in predicates.Values) { ail.net.parser.FsaTransition p_state_t = pair.PState.GetTransitionByPredicate(predicate); ail.net.parser.FsaTransition q_state_t = pair.QState.GetTransitionByPredicate(predicate); if ((p_state_t == (object)null || q_state_t == (object)null)) { continue; } ail.net.parser.FsaState p_state = (ail.net.parser.FsaState)States[p_state_t.End]; ail.net.parser.FsaState q_state = (ail.net.parser.FsaState)States[q_state_t.End]; if ((object)p_state == (object)q_state) // pairs with same states are assumped unmarked { continue; } ail.net.parser.FsaPair sigma_pair = GetPairFromStates(p_state, q_state, table); if (sigma_pair.Marked) { pair.Marked = true; process = true; } } } } if (!process) { break; } } ResetMarkedStates(); // build partition foreach (ail.net.parser.FsaState state in states) { if (!state.Marked) { // add equivalent groups, optimistic assumption ail.net.parser.FsaStateSet group = new ail.net.parser.FsaStateSet(0); for (int i = 0; i < state.Id; i++) { ail.net.parser.FsaPair pair = GetPairFromStates((ail.net.parser.FsaState)States[i], state, table); if (!pair.Marked) { if ((object)pair.QState != (object)state) { if (!pair.QState.Marked) { group.States.Add(pair.QState.Id, pair.QState); } } else { if (!pair.PState.Marked) { group.States.Add(pair.PState.Id, pair.PState); } } } } if (group.States.Count > 0) { group.States.Add(state.Id, state); group.Id = GroupCounter.Next(); // correct id xio_partition.Add(group.Id, group); foreach (ail.net.parser.FsaState group_state in group.States.Values) { group_state.Marked = true; } } } } foreach (ail.net.parser.FsaState state in states) { if (!state.Marked) { // add non-equivalent groups ail.net.parser.FsaStateSet group = new ail.net.parser.FsaStateSet(GroupCounter.Next()); group.States.Add(state.Id, state); xio_partition.Add(group.Id, group); } } ResetMarkedStates(); }
private void BuildPrimaryPartition(ref Hashtable xio_partition) { // builds primary partition, which consist of two groups: {F} anf {Q-F} ail.net.framework.Assert.NonNullReference(xio_partition, "xio_partition"); xio_partition.Clear(); ail.net.parser.FsaStateSet nf_states = new ail.net.parser.FsaStateSet(GroupCounter.Next()); // non-final states ail.net.parser.FsaStateSet fn_states = new ail.net.parser.FsaStateSet(GroupCounter.Next()); // final states xio_partition.Add(nf_states.Id, nf_states); // final states will be split and add later foreach (ail.net.parser.FsaState state in States.Values) { if (IsFinalState(state)) { fn_states.States.Add(state.Id, state); } else { nf_states.States.Add(state.Id, state); } } // also, for lexical analyzer we should separate final states by tokens into different groups Hashtable subgroups = new Hashtable(); ail.net.parser.FsaStateSet group = new ail.net.parser.FsaStateSet(GroupCounter.Next()); ail.net.parser.FsaState pin_state = (ail.net.parser.FsaState)ail.net.framework.Functor.FirstElementOfCollection(fn_states.States.Values); group.States.Add(pin_state.Id, pin_state); subgroups.Add(group.Id, group); _start: foreach (ail.net.parser.FsaState state in fn_states.States.Values) { if (state.Marked) { continue; } ail.net.parser.FsaStateSet subgroup_to_add = null; // find subgroup it may belong to foreach (ail.net.parser.FsaStateSet subgroup in subgroups.Values) { foreach (ail.net.parser.FsaState subgroup_state in subgroup.States.Values) { if (state.Token.Type == subgroup_state.Token.Type) { subgroup_to_add = subgroup; break; } } if (subgroup_to_add != (object)null) { break; } } if (subgroup_to_add == (object)null) // not found - split { ail.net.parser.FsaStateSet new_group = new ail.net.parser.FsaStateSet(GroupCounter.Next()); new_group.States.Add(state.Id, state); subgroups.Add(new_group.Id, new_group); state.Marked = true; goto _start; // fortunately not so many final states :(( } else { if (!subgroup_to_add.States.Contains(state.Id)) { subgroup_to_add.States.Add(state.Id, state); } } } // clean up _reset: foreach (ail.net.parser.FsaState state in fn_states.States.Values) { if (state.Marked) { state.Marked = false; fn_states.States.Remove(state.Id); goto _reset; } } // insert subgroups foreach (ail.net.parser.FsaStateSet subgroup in subgroups.Values) { xio_partition.Add(subgroup.Id, subgroup); } }