protected Expression compute() {
        while (afterCollapser!=null || beforeCollapser!=null || this.csmatcher.hasNext()) {
            //
            // Square Matching after mismatch point
            //
            if (afterCollapser!=null) {
                this.last = collapse(afterCollapser);
                if (!afterCollapser.hasNext()) afterCollapser = null;
                
                Expression result = wrapperGeneralization(csquare,first,last);
                if (result!=null) return result;
                
                continue;
            }
            //
            // Square Matching before mismatch point
            //
            if (beforeCollapser!=null) {
                this.first = collapse(beforeCollapser);
                if (!beforeCollapser.hasNext()) beforeCollapser = null;
                
                afterCollapser = getAfterCollapser(this.csquare, this.space);
                
                continue;
            }
            //
            // Candidate Square Evaluation
            //
            this.csquare = csmatcher.next();
            if (!this.csquare.isSingleton()) {
                log.finest(" operator "+getId()+": collapsing before: "+dir.uTurn());
                beforeCollapser = new Collapser(csquare, csmatcher.getRemainingRegion(), dir.uTurn(), space);
            }
        }
        this.expired = true;
        return null;
    }