public virtual IIntSet Complement(IIntSet set) { if (set == null) { return(this.Complement()); } return(set.Subtract(this)); }
/** 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()); */ }