boolean find(Cnfa cnfa) {
        int begin;
        int end = -1;
        int cold;
        int open;       /* open and close of range of possible starts */
        int close;
        boolean hitend;
        boolean shorter = 0 != (g.tree.flags & Subre.SHORTER);
        boolean lookingAt = 0 != (eflags & Flags.REG_LOOKING_AT);
        int[] coldp = new int[1];
        Dfa d = new Dfa(this, cnfa);

        if (lookingAt) {
            /*
             * shortest is faster than longest. So, we want to check with it.
             * However, since we aren't making a 'search re' with an extra .* on
             * the front, we don't add an extra requirement to make progress on the
             * very first arc. If the expression has something like a* at the front,
             * it can 'no-progress' consuming the a characters.
             * All of this casts doubts on the 'requireInitialProgress' feature -- at all.
             * These initial calls to shortest should be all the opportunity we need
             * to do 'lookingAt'.
             */
            close = d.shortest(0, 0, data.length(), coldp, null);
            cold = 0;
        } else {
            /* First, a shot with the search RE. */
            Dfa s = new Dfa(this, g.search);
            close = s.shortest(0, 0, data.length(), coldp, null);
            cold = coldp[0];
        }

        if (close == -1) {      /* not found */
            return false;
        }

    /* find starting point and match */
        open = cold;
        cold = -1;

        for (begin = open; begin <= close; begin++) {
            /*
             * if LOOKING_AT, we can't validly have a 'begin' after 'open'.
             * I'm not sure this test can even ever go off, since the 'shortest' test
             * up above should accomplish the same thing.
             */
            if (begin > 0 && lookingAt) {
                return false;
            }

            boolean[] hitendp = new boolean[1];
            if (shorter) {
                end = d.shortest(begin, begin, data.length(), null, hitendp);
            } else {
                end = d.longest(begin, data.length(), hitendp);
            }
            hitend = hitendp[0];

            if (hitend && cold == -1) {
                cold = begin;
            }
            if (end != -1) { /* success */
                break;      /* NOTE BREAK OUT */
            }
        }

        if (end == -1) {
            return false;
        }

        /* and pin down details */
        match.set(0, new RegMatch(begin, end));

        // no need to do the work.
        return re.nsub <= 0 || dissect(g.tree, begin, end);
    }
boolean find ( Cnfa cnfa ) { int begin ; int end = - 1 ; int cold ; int open ; int close ; boolean hitend ; boolean shorter = 0 != ( g . tree . flags & Subre . SHORTER ) ; boolean lookingAt = 0 != ( eflags & Flags . REG_LOOKING_AT ) ; int [ ] coldp = new int [ 1 ] ; Dfa d = new Dfa ( this , cnfa ) ; if ( lookingAt ) { close = d . shortest ( 0 , 0 , data . length ( ) , coldp , null ) ; cold = 0 ; } else { Dfa s = new Dfa ( this , g . search ) ; close = s . shortest ( 0 , 0 , data . length ( ) , coldp , null ) ; cold = coldp [ 0 ] ; } if ( close == - 1 ) { return false ; } open = cold ; cold = - 1 ; for ( begin = open ; begin <= close ; begin ++ ) { if ( begin > 0 && lookingAt ) { return false ; } boolean [ ] hitendp = new boolean [ 1 ] ; if ( shorter ) { end = d . shortest ( begin , begin , data . length ( ) , null , hitendp ) ; } else { end = d . longest ( begin , data . length ( ) , hitendp ) ; } hitend = hitendp [ 0 ] ; if ( hitend && cold == - 1 ) { cold = begin ; } if ( end != - 1 ) { break ; } } if ( end == - 1 ) { return false ; } match . set ( 0 , new RegMatch ( begin , end ) ) ; return re . nsub <= 0 || dissect ( g . tree , begin , end ) ; }
find - find a match for the main NFA (no-complications case)
<p>
First, it runs the 'search machine' in non-greedy mode (shortest). The 'search machine' is the NFA with
.* added to the front and the back, more or less. See 'makesearch'. In many cases, running the search machine
'shortest' is considerably faster than running the actual regular expression in greedy (longest). So,
even though this may seem like it would take extra time doing an extra scan, the alternative is much slower.
The search machine tells you if the expression can be found anywhere, and, if so, where is the furthest possible
end.
</p>
<p>
If the search machine succeeds, the does an iteration to find the exact bounds;
the loop uses 'longest' or 'shortest' as appropriate to the flags. In C, there was an option to
_only_ run the search machine and return a simple boolean with no bounds.
We have no API for that via an ExecFlag.
</p>
<p>
If the top-level API call is 'lookingAt', we never want to scan down the data looking for matches. But 'shortest'
can still be much faster than 'longest'. So, the code runs the original machine first. If non-greedy expressions
were very common, I suppose that it would be faster to omit this step in that case. Thereafter, the loop has
a check to bail if these is no match at the beginning of the data, which is the constraint of lookingAt.
</p>