Packrat Parsing (2002)
pdos.csail.mit.edu
pdos.csail.mit.edu
At some point I tried to use a similar idea to build an incremental parser generator for Emacs (2). Currently abandonware, but think it has potential!
Lots of regular expressions were used before and without control of the documents (which change over time) this kind of code was just unmanageably difficult to maintain.
Being able to use negative look ahead with lists of grammar symbols provides an incredibly large amount of power to resolve ambiguities and makes it relatively easy to arrive at an explainable grammar capable of handling “every sample we’ve seen so far drawn from an only partially observable language” ...
Working memory was on the megabyte scale in the mid ‘80s, plus or minus an order of magnitude. Any parsing algorithm which could require memory proportional to input size (like pack rat parsing with memorization) was nothing more than a thought experiment.
Slide forward to the 2000’s and Packrat Parsing can be a practical system for some scenarios.
Now from the ~2020 perspective; packrat parsing and parsing combinator libraries are trivial to use, possibly consuming uncounted mountains of RAM, but we have 10000 times more RAM in our machines than the ‘80s and it just doesn’t matter if you can prove whether the upper bound memory use of your parsing algorithm is a function of parse tree depth or input length.
But PEGs for most languages translate trivially into recursive descent parsers with limited lookahead. In most languages where there's a risk of significant backtracking there tends to be relatively simple ways of minimizing it by relatively simple restructuring of the grammer without any reason to resort to packrat parsing. I'm sure there are cases where it's tricky enough that a packrat parser simplifies it substantially, but I just haven't come across any where it's particularly compelling.
Basically any recursive descent created from a PEG with deep lookahead can usually have the lookahead reduced by recognising any shared prefix to any set of choices first, and then the remainder of the choices.
Most of the remaining interesting cases are usually solved by trivial restructuring of the parse tree afterwards.
That may not always be enough, but it is enough for most real use-cases.
Packrat parsing is appealing because it saves people from thinking about how to structure a PEG in a way that minimize the worst case lookahead, but the effort needed to reduce the lookahead is rarely particularly hard, and most real-life examples I've seen where composing parsers is useful have tended to diverge quickly enough to require very little lookahead.