Re: "tweetable" "symbolic" hex COM loader
Dave Long <[email protected]> Sat, 19 Oct 2013 20:05:31 +0200
| Newsgroups | gmane.culture.people.kragen.discuss |
|---|---|
| Message-ID | <[email protected]> |
> A really efficient modern NFA engine would probably skip these
> shenanigans and work in terms of bitvectors, alas.
It would appear that NFA's are basically polynomials:
Sn = Mn /\ T * M(n-1) /\ T * T * M(n-2) /\ ... /\ T^n * S0
where Sn : state at input n
Mn : literal matches at input n
T : transfer matrix
which, thanks to Horner's rule, can be evaluated iteratively:
Sn = Mn /\ T * (Mn-1 /\ T * ( ... ) )
and hence (with appropriate choice of boolean parity) can be
expressed as:
Sn = (M + T * S(n-1))
which, being in matrix multiply-accumulate form, implies that modern
NFA engines might well involve DSP/GPU shenanigans, or whatever is
most suitable for often-sparse matrices.
(one might also imagine running the input in parallel across a state
at a time, and seeing what actually links up once one has processed
the final state. This is unlikely to be useful, but maybe it's the
angels algorithm? (Turing commented that although angels might get
away with having a single box with an infinite number of symbols, the
rest of us should stick with a finite set of symbols on an infinite
tape))
>> Based on Cox' description of the Thompson construction (and dim
>> memories of the Dragon book), I bashed out a nondeterministic regex
>> machine in an evening. (Thompson, naturally, takes a route[0] that
>> comes naturally to language implementers[1]) It initially seemed a
>> bit wasteful, for we extract the tree structure once while parsing,
>> flatten everything down to a list of VM ops, and then essentially
>> implicitly reconstruct the tree when following the epsilon
>> transitions. So the next version wound up very similar to Doug
>> McIlroy's recent Haskell interpretation:
>
> Which I haven't read, but it sounds like you might've also wound up
> similar to http://sebfisch.github.io/haskell-regexp/regexp-play.pdf
> (which I haven't read either, but it represents a set of NFA states as
> a regex tree with marks on the occupied states, apparently)
Neither of us went that far. Labels for states are kind of
arbitrary, so it's an obvious design decision. I had considered
using the tree, but thought it was overkill to index states by tree
path, when the ordinal of the literal in the original regexp string
(plus a start and accepting state at -1 and N) provides a nice small
integer key suitable for a low-level state machine. In fact, this
separates concerns nicely, as one can build the literal match pool
completely independently of the transfer matrix (as one might expect
from the equation above). Just like there's a difference between map
and reduce, here the leaves of the parse tree go, in order, into the
literal pool ("state definitions"), and the branches get
independently folded down to provide the transfer matrix ("epsilon
transitions"); submatch boundaries (which I postprocess) are yet
another independent fold. Note that literal leaves also pass
unchanged through Thompson's postfix pass; it's just that instead of
separating his basic blocks and control flow at that point, he merges
them. However, the tree (or in this case, graph) approach produces
its motivation in Scene iii, Act 1, when they start interpreting
infinite regexps ...
-Dave
--
To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-discuss