Beispiel #1
0
 public virtual IIntSet Complement(IIntSet set)
 {
     if (set == null)
     {
         return(this.Complement());
     }
     return(set.Subtract(this));
 }
Beispiel #2
0
        /** Add label uniquely and disjointly; intersection with
         *  another set or int/char forces breaking up the set(s).
         *
         *  Example, if reachable list of labels is [a..z, {k,9}, 0..9],
         *  the disjoint list will be [{a..j,l..z}, k, 9, 0..8].
         *
         *  As we add NFA configurations to a DFA state, we might as well track
         *  the set of all possible transition labels to make the DFA conversion
         *  more efficient.  W/o the reachable labels, we'd need to check the
         *  whole vocabulary space (could be 0..\uFFFF)!  The problem is that
         *  labels can be sets, which may overlap with int labels or other sets.
         *  As we need a deterministic set of transitions from any
         *  state in the DFA, we must make the reachable labels set disjoint.
         *  This operation amounts to finding the character classes for this
         *  DFA state whereas with tools like flex, that need to generate a
         *  homogeneous DFA, must compute char classes across all states.
         *  We are going to generate DFAs with heterogeneous states so we
         *  only care that the set of transitions out of a single state are
         *  unique. :)
         *
         *  The idea for adding a new set, t, is to look for overlap with the
         *  elements of existing list s.  Upon overlap, replace
         *  existing set s[i] with two new disjoint sets, s[i]-t and s[i]&t.
         *  (if s[i]-t is nil, don't add).  The remainder is t-s[i], which is
         *  what you want to add to the set minus what was already there.  The
         *  remainder must then be compared against the i+1..n elements in s
         *  looking for another collision.  Each collision results in a smaller
         *  and smaller remainder.  Stop when you run out of s elements or
         *  remainder goes to nil.  If remainder is non nil when you run out of
         *  s elements, then add remainder to the end.
         *
         *  Single element labels are treated as sets to make the code uniform.
         */
        protected virtual void AddReachableLabel(Label label)
        {
            if (_reachableLabels == null)
            {
                _reachableLabels = new OrderedHashSet <Label>();
            }

            /*
             * [email protected]("addReachableLabel to state "+dfa.decisionNumber+"."+stateNumber+": "+label.getSet().toString(dfa.nfa.grammar));
             * [email protected]("start of add to state "+dfa.decisionNumber+"."+stateNumber+": " +
             *      "reachableLabels="+reachableLabels.toString());
             */
            if (_reachableLabels.Contains(label))
            {
                // exact label present
                return;
            }
            IIntSet t         = label.Set;
            IIntSet remainder = t;                      // remainder starts out as whole set to add
            int     n         = _reachableLabels.Count; // only look at initial elements

            // walk the existing list looking for the collision
            for (int i = 0; i < n; i++)
            {
                Label rl = _reachableLabels[i];

                /*
                 * [email protected]("comparing ["+i+"]: "+label.toString(dfa.nfa.grammar)+" & "+
                 *      rl.toString(dfa.nfa.grammar)+"="+
                 *      intersection.toString(dfa.nfa.grammar));
                 */
                if (!Label.Intersect(label, rl))
                {
                    continue;
                }
                //[email protected](label+" collides with "+rl);

                // For any (s_i, t) with s_i&t!=nil replace with (s_i-t, s_i&t)
                // (ignoring s_i-t if nil; don't put in list)

                // Replace existing s_i with intersection since we
                // know that will always be a non nil character class
                IIntSet s_i          = rl.Set;
                IIntSet intersection = s_i.And(t);
                _reachableLabels[i] = new Label(intersection);

                // Compute s_i-t to see what is in current set and not in incoming
                IIntSet existingMinusNewElements = s_i.Subtract(t);
                //[email protected](s_i+"-"+t+"="+existingMinusNewElements);
                if (!existingMinusNewElements.IsNil)
                {
                    // found a new character class, add to the end (doesn't affect
                    // outer loop duration due to n computation a priori.
                    Label newLabel = new Label(existingMinusNewElements);
                    _reachableLabels.Add(newLabel);
                }

                /*
                 * [email protected]("after collision, " +
                 *      "reachableLabels="+reachableLabels.toString());
                 */

                // anything left to add to the reachableLabels?
                remainder = t.Subtract(s_i);
                if (remainder.IsNil)
                {
                    break; // nothing left to add to set.  done!
                }

                t = remainder;
            }
            if (!remainder.IsNil)
            {
                /*
                 * [email protected]("before add remainder to state "+dfa.decisionNumber+"."+stateNumber+": " +
                 *      "reachableLabels="+reachableLabels.toString());
                 * [email protected]("remainder state "+dfa.decisionNumber+"."+stateNumber+": "+remainder.toString(dfa.nfa.grammar));
                 */
                Label newLabel = new Label(remainder);
                _reachableLabels.Add(newLabel);
            }

            /*
             * [email protected]("#END of add to state "+dfa.decisionNumber+"."+stateNumber+": " +
             *      "reachableLabels="+reachableLabels.toString());
             */
        }