Top-down and bottom-up are not mutually exclusive. At least not
completely. But self-modifying parsers are *much* easier to do with
top-down than bottom-up, because the whole point of bottom-up is that
you can analyze the grammar at "compile" (parser generation) time, and
propagate the knowledge throughout the rule engine.

A simple example is /fish|job|petunia/. Rather than trying to match
/fish/ and upon failure, trying /job/, and as a last resort /petunia/,
you could do a dispatch table on the first letter and never have to
fall back to anything. In the case of /fish|job|<petunia>/, however,
you can't guarantee that FIRST(<petunia>) will always be "p".

You could generate both parsers and then use a notification or
dependency system to pick which to use, but done naively you end up
with an exponential number of parsers and the logic is likely to be
both slow and a bug magnet.

You could compile the parser assuming everything is final and then at
runtime regenerate the entire parser if anything changes. Which
wouldn't work for long, but perhaps you could break the grammar down
into components that are individually compiled bottom-up, but
coordinated top-down. Then you could limit the scope of recompiles in
the bottom-up components, and not need recompiles in the top-down
structure. The decisions of where to break things down would be quite
similar to a regular compiler's inlining decisions. It may be that
grammars are just too recursive for this to help much, though.

I suspect a slight variant of the above may work best. Rather than
doing a full-out LALR(1) parser for the bottom-up components, you'd do
a somewhat more naive but still table-driven (shift/reduce) parser,
carefully limiting what it is assuming about the FIRST() etc. of the
rules within it. That should limit the impact of changes, and simplify
the logic of what needs to be done differently when a change is
detected.

On May-11, Matt Fowles wrote:
>
> Perhaps Perl 6 grammars should provide an is parsed trait that
> allows one to specify which type of parsing to use, then we could
> dictate that the default behavior for parsing or perl itself is
> shift reduce parsing rather than recursive descent.

Optimization hints could also be very helpful, or we could even
default to a total recursive-descent parser and only attempt bottom-up
precomputation if the grammar author specifically says it's ok. The
main problem being that people will say lots of things if it makes
their code faster, without having any idea what it actually means.

Reply via email to