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;
                        }
                    }
                }
            }
        }