Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

makeExprParser + precedence climbing #1625

Open
sshine opened this issue Jan 17, 2023 · 3 comments
Open

makeExprParser + precedence climbing #1625

sshine opened this issue Jan 17, 2023 · 3 comments

Comments

@sshine
Copy link

sshine commented Jan 17, 2023

The nom 7.0 roadmap (#1323) mentions, among many things,

handling precedence in expressions (something like Megaparsec's makeExprParser would be nice)

I am a big fan of Megaparsec's makeExprParser, and if I'm not mistaken, nom still does not have an equivalent, does it?

Here is another idea: Following this post, this comment suggested something more efficient: Parsing expressions using precedence climbing. While makeExprParser converts a nice, declarative table of operators into an LL parser, this parser is somewhat inefficient compared to precedence climbing.

It should be possible to convert a similar operator table into a precedence climbing parser.

The prerequisite for making precedence climbing on a &str is that it's fenced off; i.e. while a makeExprParser parser is still just an LL parser that will leave stuff after the expression unconsumed, a precedence climber will assume that the expression can be analysed from both sides of the &str, i.e. one needs to have fenced off a &str that contains an expression and then apply the precedence climber. That will feel slightly less natural in nom.

@cenodis
Copy link
Contributor

cenodis commented Jul 18, 2023

Related: #1362
A combinator to parse tokens with operator precedence. Based on the shunting yard algorithm.

@stefnotch
Copy link

stefnotch commented Dec 23, 2023

Copied from the duplicate pratt parsing issue

Implementing pratt parsing (or precedence climbing, which is supposedly the same algorithm) could be useful. I quite like it for parsing mathematical expressions with lots of different operators, since I no longer has to bend my parsing rules to fit, and can instead specify the binding power and associativity.

There are other libraries that have implemented this, for example

@ilonachan
Copy link

Very much not a parsing expert here, but I followed the tutorial linked by @stefnotch to implement a pratt parser in pure nom: https://gist.github.com/ilonachan/3d92577265846e5327a3011f7aa30770

As the first article linked by @stefnotch points out, this should also cover precedence climbing, since they are the same algorithm (with left-/right-associativity being modeled by whether a binary operator's right/left binding power is greater than the other).

There were some tricky edges, but I think the API turned out fairly nice; this is probably such a common use case that adding it to nom itself could be considered. I haven't published this as a crate or made a PR (yet) but feel free to use if it helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants