Beispiel #1
0
        /// <summary>
        /// Refine the partitions by splitting incompatible states
        /// </summary>
        internal void RefinePartitions()
        {
            int generation = 0;

            while (worklist.Count > 0)
            {
                List <DFSA.DState> predSet = null;
                //
                // We are going to split all blocks with respect to a
                // particular (Block, Symbol) pair.
                // Fetch the pair components.
                //
                // In order to avoid having to reset the predCount ints
                // all the time we keep a generation count to indicate to
                // which pass through the loop the counts apply.
                //
                PartitionBlock blk = worklist.Peek();

                int sym = blk.Sym - 1;
                if (sym < 0)
                {
                    worklist.Pop();           // Remove block from the worklist.
                    continue;                 // Go around again to get new block.
                }
                generation++;
                predSet = new List <DFSA.DState>();
                //
                // Form a set of all those states that have a
                // next-state in "blk" on symbol "sym".
                // Note that despite the nested loops the
                // complexity is only N == number of states.
                //
                foreach (DFSA.DState dSt in blk.members)
                {
                    if (dSt.HasPredecessors())
                    {
                        List <DFSA.DState> prds = dSt.GetPredecessors(sym);
                        if (prds != null && prds.Count > 0)
                        {
                            foreach (DFSA.DState pSt in prds)
                            {
                                // The same predecessor state might appear on the
                                // list for more than one state of the blk.members.
                                // States should only appear once in the predSet "set"
                                if (pSt.listOrd != generation) // This predecessor is not in the set already
                                {
                                    PartitionBlock predBlk = (pSt.block as PartitionBlock);
                                    pSt.listOrd = generation;
                                    if (predBlk.Gen != generation)
                                    {
                                        predBlk.Gen       = generation;
                                        predBlk.PredCount = 0;
                                    }
                                    predSet.Add(pSt);       // Add the predecessor to the set
                                    predBlk.PredCount++;
                                }
                            }
                        }
                    }
                }
                blk.Sym--;                         // "Remove" (blk,sym) from the pair list.
                //
                // Now, if the predecessor set is not empty,
                // we split all blocks with respect to (blk,sym)
                //
                if (predSet.Count != 0)
                {
                    List <PartitionBlock> splits = new List <PartitionBlock>();
                    foreach (DFSA.DState lSt in predSet)
                    {
                        PartitionBlock tBlk = null;
                        PartitionBlock lBlk = (lSt.block as PartitionBlock);
                        if (lBlk.PredCount != lBlk.MemberCount) // Need to split this block
                        {
                            tBlk = lBlk.twinBlk;
                            if (tBlk == null)
                            {
                                tBlk = MkNewBlock();
                                splits.Add(tBlk);
                                lBlk.twinBlk = tBlk;
                                tBlk.twinBlk = lBlk;
                            }
                            lBlk.MoveMember(lSt, tBlk);
                            lSt.block = tBlk;
                        }
                    }
                    foreach (PartitionBlock tBlk in splits)
                    {
                        PartitionBlock lBlk = tBlk.twinBlk;
                        PartitionBlock push = null;
                        if (lBlk.Sym == 0)    // lBlk is not currently on the list so push smaller block
                        {
                            if (lBlk.MemberCount < tBlk.MemberCount)
                            {
                                push = lBlk;
                            }
                            else
                            {
                                push = tBlk;
                            }
                        }
                        else                 // lBlk is on the list with Sym > 0
                        {
                            push = tBlk;
                            if (lBlk.MemberCount < tBlk.MemberCount)
                            {
                                // tBlk has the larger cardinality, so give it the smaller Sym value
                                tBlk.Sym = lBlk.Sym;
                                lBlk.Sym = dfsa.MaxSym;
                            }
                        }
                        worklist.Push(push);
                        lBlk.twinBlk = null;
                        tBlk.twinBlk = null;
                    }
                }
            } // end of while loop...
        }