Why Sponsor Oils? | blog | oilshell.org
I've noticed that my November posts on expression parsing with Pratt's algorithm are popular and still drawing readers.
So here's an index of them, including yesterday's update, with related links.
After parsing arithmetic in OSH, I noticed that the precedence climbing algorithm is a special case of the earlier Pratt parsing algorithm. But see the update below.
I reviewed four articles, in order to motivate a different code structure.
Crockford deserves credit for reviving Pratt's algorithm, but I think his idiosyncratic style leaked into almost every future exposition of it.
In this article, I explain the code in my pratt-parsing-demo repo.
Why? I tend to use classes somewhat formally, either for dependency inversion or for maintaining invariants on state. If everything's a class, then nothing is.
A minor update to correct a misleading notion.
In November, I recommended dropping the "precedence climbing" name to avoid confusion. After looking at real code, I've changed my view.
An encyclopedic update from Jean-Marc Bourguet.
The post How Desmos Uses Pratt Parsers may be useful if you prefer to read code in TypeScript. See desmosinc/pratt-parser-blog-code.
They also compare Pratt Parsing to using Jison, a LR(1) parser generator like Yacc or GNU Bison.
Simple But Powerful Pratt Parsing. An introduction to the algorithm, with code in Rust. (reddit comments)
The post says that the algorithm is both recursive and iterative, which is a good point.
Here's a related observation that may also help. You can divide recursive algorithms into two categories:
function count(node) {
return 1 + count(node.left) + count(node.right)
}
Algorithms where state is mutated while recursing. Recursive descent parsing and Pratt Parsing both fall in this category, and that's one thing that makes them harder to understand (and debug).
In addition to returning or evaluating subexpressions, you advance through
the token stream while recursing. This is done in the Next()
call on
line 222 of
tdop.py.
Note that ParseUntil()
and the set of nud()
/ led()
functions are
mutually recursive.
Nice diagrams in this article:
Demystifying Pratt Parsers (martin.janiczek.cz
via lobste.rs)
17 points, 3 comments on 2023-07-03