internal RangeLiteral(int ch) { list = new RangeList(false); list.Add(new CharRange(ch, ch)); // AddToRange }
internal RangeLiteral(bool invert) { list = new RangeList(invert); }
/// <summary> /// Return a new RangeList that is the intersection of /// "this" and rhOp. Neither operand is mutated. /// </summary> /// <param name="rhOp"></param> /// <returns></returns> internal RangeList AND(RangeList rhOp) { if (!isCanonical || !rhOp.isCanonical) { throw new GplexInternalException("RangeList non canonicalized"); } if (this.ranges.Count == 0 || rhOp.ranges.Count == 0) { return(new RangeList(false)); // return empty RangeList } int thisIx; int rhOpIx = 0; int thisNm = this.ranges.Count; int rhOpNm = rhOp.ranges.Count; List <CharRange> newList = new List <CharRange>(); RangeList result = new RangeList(newList, false); CharRange rhOpElem = rhOp.ranges[rhOpIx++]; for (thisIx = 0; thisIx < thisNm; thisIx++) { CharRange thisElem = this.ranges[thisIx]; // Attempt to find an overlapping element. // If necessary fetch new elements from rhOp // until maxChr of the new element is greater // than minChr of the current thisElem. while (rhOpElem.maxChr < thisElem.minChr) { if (rhOpIx < rhOpNm) { rhOpElem = rhOp.ranges[rhOpIx++]; } else { return(result); } } // It is possible that the rhOpElem is entirely beyond thisElem // It is also possible that rhOpElem and several following // elements are all overlapping with thisElem. while (rhOpElem.minChr <= thisElem.maxChr) { // process overlap newList.Add(new CharRange( (thisElem.minChr < rhOpElem.minChr ? rhOpElem.minChr : thisElem.minChr), (thisElem.maxChr < rhOpElem.maxChr ? thisElem.maxChr : rhOpElem.maxChr))); // If rhOpElem extends beyond thisElem.maxChr it is possible that // it will overlap with the next thisElem, so do not advance rhOpIx. if (rhOpElem.maxChr > thisElem.maxChr) { break; } else if (rhOpIx == rhOpNm) { return(result); } else { rhOpElem = rhOp.ranges[rhOpIx++]; } } } return(result); }
internal PartitionElement(List <CharRange> ranges, bool invert) { ord = nextOrd++; list = new RangeList(ranges, invert); }
/// <summary> /// Refine the current partition with respect /// to the given range literal "lit". /// </summary> /// <param name="lit">The Range Literal</param> internal void Refine(RangeLiteral lit) { int idx; int max = elements.Count; // because this varies inside the loop // // For each of the *current* elements of the partition do: // for (idx = 0; idx < max; idx++) { PartitionElement elem = elements[idx]; RangeList intersection = lit.list.AND(elem.list); // // There are four cases here: // (1) No intersection of lit and elem ... do nothing // (2) Literal properly contains the partition element ... // Add this element to the equivClasses list of this lit. // Add this lit to the list of literals dependent on "elem". // The intersection of other parts of the literal with other // elements will be processed by other iterations of the loop. // (3) Literal is properly contained in the partition element ... // Split the element into two: a new element containing the // intersection, and an updated "elem" with the intersection // subtracted. All literals dependent on the old element are // now dependent on the new element and (the new version of) // this element. The literal cannot overlap with any other // element, so the iteration can be terminated. // (4) Literal partially overlaps the partition element ... // Split the element as for case 2. Overlaps of the rest // of the literal with other elements will be dealt with by // other iterations of the loop. // if (!intersection.IsEmpty) // not empty intersection { // Test if elem is properly contained in lit // If so, intersection == elem ... if (intersection.EQU(elem.list)) { elem.literals.Add(lit); lit.equivClasses.Add(elem.ord); } else { PartitionElement newElem = new PartitionElement(intersection.Ranges, false); elements.Add(newElem); lit.equivClasses.Add(newElem.ord); newElem.literals.Add(lit); // // We are about to split elem. // All literals that include elem // must now also include newElem // foreach (RangeLiteral rngLit in elem.literals) { rngLit.equivClasses.Add(newElem.ord); newElem.literals.Add(rngLit); } elem.list = elem.list.SUB(intersection); // // Test if lit is a subset of elem // If so, intersection == lit and we can // assert that no other loop iteration has // a non-empty intersection with this lit. // if (intersection.EQU(lit.list)) { return; } } } } }