The conversion from NFA to DFA is the job of the class tt(DFA) object
(cf. figure ref(DFAFIG))

    figure(images/dfa)(The DFA class data members)(DFAFIG)

The DFA uses the externally available rules, states and character ranges
and builds a vector of tt(DFARow)s, named tt(d_row). It has the following data
members:
    itemization(
    itt(d_row): the vector of tt(DFARow) objects, defining the rows of the DFA
(cf. section ref(DFAROW));
    itt(d_stateSet): a vector of sets of tt(State) indices. There are as many
sets in this vector as there are elements in tt(d_row), and each element holds
the indices of the tt(State) objects in tt(d_states) that are represented by
the matching tt(DFARow) object.
    itt(d_sawAccept): a tt(bool) set to em(true) while processing
tt(TailCount) objects once a row representing an tt(ACCEPT) state has been
encountered. tt(TailCounts) are processed by tt(computeTailCounts), see below.
    itt(d_rule): the rule index represented by a tt(TailCount) object
in tt(d_row[0]). 
    itt(d_verbose): shadows the presence of the tt(--verbose) program flag.
    )

Building the DFA from the NFA is the task of tt(DFA::build). 

Each row of tt(d_row) defines a state in the DFA. The Rule numbers of the
Rules defining a mini scanner received as tt(build)'s tt(vector<size_t>)
parameter. 

tt(DFA::build) initially stores the start states of the rules of its mini
scanner in its tt(d_stateSet[0])sups(th) element, which is a set (cf. figure
ref(DFAFIG1)). This is done by tt(DFA::fillStartSet)

    figure(images/dfa1)(Creating the start states for row 0)(DFAFIG1)

Next, the e-closure of this initial set of states is computed. The e-closure
algorithm is described in ASU's dragon book (1986, figure 3.26). It
essentially adds all states that can be reached from each element in the
current set of states on an empty transition. The e-closure is computed by
tt(States::eClosure).

At this point there is an element in tt(DFA::d_stateSet), but not yet an
element in tt(DFA::d_row). By adding a tt(DFARow) (see section ref(DFAROW)) to
tt(d_row) we associate a tt(DFARow) with an initial set of states. 

Once the new DFA has been added to tt(d_row) its transitions are probed by
tt(DFARow::transitions) (see section ref(DFAROW)).

bf(DFA::keepUniqueRows)

    Having determined the transitions tt(build) proceeds to remove
implied/identical rows, calling tt(DFA::keepUniqueRows). This latter function
visits each of the rows of the DFA, testing whether an existing row has the
same transitions and final state information as the current row. `Same
transitions' means that the transitions of the current (under inspection) row
are present in an earlier row; `same final state information' means that the
current row is a final state for the same rule(s) as an earlier row. In such
situations the current row can be merged with the earlier row, keeping the
earlier row. The (later) row can then be removed as transitions from it are
identical to those from the earlier row. This may happen, as the NFA
construction algorithm may define more empty edges than strictly necessary,
sometimes resulting in additional rows in the DFAs. As an example, consider
the pattern tt((a|ab)+/(a|ba)+), producing the DFA
    center(
    table(5)(llrc)(
    rowline()
    row(cell()cells(2)(Input Chars))
    row(cell(StateSet) ccell(a) ccell(b) ccell(Final) ccell(Accept))
    rowline(cell()cellsline(2)(4))

    row(cell(0)ccell(1))
    row(cell(1)ccell(2)ccell(3))
    row(cell(2)ccell(2)ccell(3)   cell(0:1))
    row(cell(3)ccell(4)ccell(5))
    row(cell(4)ccell(2)ccell(3)   cell(0:2))
    row(cell(5)ccell(6)cell()     cell()cell(0:++1))
    row(cell(6)ccell(7)ccell(5)   cell(0))
    row(cell(7)ccell(7)ccell(5)   cell(0))
    rowline()
    ))
    Rows 6 and 7 are identical, as are rows 2 and 4. For row 4 the (erroneous,
if |TAIL| should be as short as possible) |TAIL| = 2 is shown, resulting from
tt(aba) being interpreted as HEAD: tt(a) and TAIL: tt(ba). 

But when |TAIL| should be minimized tt(aba) should be interpreted as HEAD:
tt(ab) and TAIL tt(a), resulting in transitions 0 -> 1 -> 3 -> 2, with |TAIL|
= 1. This happens when row 4 is merged to row 2. Having merged the rows,
former transitions to the now removed rows must of course be updated to the
merging row. So row 3 must transit to 2 when receiving input symbol tt(a). The
member tt(shrinkDFA) handles the shrinkage of the DFA. In this example the
final DFA becomes:
    center(
    table(5)(llrc)(
    rowline()
    row(cell()cells(2)(Input Chars))
    row(cell(StateSet) ccell(a) ccell(b) ccell(Final) ccell(Accept))
    rowline(cellsline(2)(4))

    row(cell(0)ccell(1))
    row(cell(1)ccell(2)ccell(3))
    row(cell(2)ccell(2)ccell(3) cell(0:1))
    row(cell(3)ccell(2)ccell(4))
    row(cell(4)ccell(5)cell()   cell()cell(0:++1))
    row(cell(5)ccell(5)ccell(4) cell(0))
    rowline()
    ))

bf(keepViableTailCounts)

Tail counts of rules which cannot be matched (i.e., for rules not having the
tt(viable) attribute set) are removed by this function. Rule's
tt(TailCount) elements were determined by the tt(DFARow)'s constructor (see
sections ref(DFAROW) and ref(TAILCOUNT)).

bf(computeTailCounts)

Finally, any remaining tt(TailCount) elements are processed by
tt(computeTailCounts). Each tt(TailCount) element is processed as follows
(cf. figure ref(CPTTAILCOUNTS))

    figure(images/cpttailcounts)(Computing TailCount values)(CPTTAILCOUNTS)

    itemization(
    itt(visitTailCount): initializes tt(d_sawACCEPT) to tt(false) and
tt(d_row) to the tt(TailCount)'s rule index, and then calls
tt(determineTailCount) to compute the tail sizes for the various rows of the
DFA.
    itt(determineTailCount): calls tt(setTailCount) to determine the action to
take for the tt(TailCount) object that's passed to it. The logic behind this
function's decision is shown in section ref(TAILLOGIC). If the current tail
count is computed as the previous tail count + 1 (i.e., COUNT is set), then
the computed value may conflict with a previously computed value (cf. section
ref(LOPPROBLEM)). In that case the count is set to zero, and a warning is
issued. The warning is generated by tt(setNextTailCount), called from
tt(setTailCount). This procedure is subject to change in future releases of
tt(flexc++).nl()
        If the tt(TailCount) values were updated then tt(determineTailCount)
proceeds by calling tt(transitTailCount) for each of the row's transition
map's elements. 
    itt(transitTailCount): if the destination row of a transition has a
tt(TailCount) element referring to the row stored in DFA's tt(d_row), then the
tail count for that row is determined by (indirect recursively) calling
tt(determineTailCount).
    )


