Skip to content
This repository was archived by the owner on Apr 2, 2026. It is now read-only.

Added Non-Associative associativity for Pratt Parsers.#600

Open
YunkaiZhang233 wants to merge 3 commits into
zesterer:mainfrom
YunkaiZhang233:pratt-infix-non
Open

Added Non-Associative associativity for Pratt Parsers.#600
YunkaiZhang233 wants to merge 3 commits into
zesterer:mainfrom
YunkaiZhang233:pratt-infix-non

Conversation

@YunkaiZhang233
Copy link
Copy Markdown

In current Pratt parsers, only associativity type of left and right are supported. However, according to the original designs of Pratt parsing, it should also support Non-Associative infix binary operators.

For example, consider operators == as a non-associative operator. We should be able to identify it as non-associative and therefore rejecting 1 == 2 == 3 as an expression with the numbers being atomic literals. Whilst the current design only allow == to be either left-associative or right-associative.

This PR added associativity non for infix binary operators, and changed the binding power calculation function slightly based on The Original Parsing Methodology and this article.

Copy link
Copy Markdown
Owner

@zesterer zesterer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, great work! Just a few comments.

Comment thread src/pratt.rs
match self {
Self::Left(x) => *x as u32 * 3,
Self::Right(x) => *x as u32 * 3,
Self::Non(x) => *x as u32 * 3 - 1,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this to be valid, all powers should have 1 added to them such that *x as u32 * 3 - 1 can never result in underflow.

Copy link
Copy Markdown

@TheOnlyTails TheOnlyTails Oct 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this resolve the issue here?

            Self::Left(x) => *x as u32 * 3 + 1,
            Self::Right(x) => *x as u32 * 3 + 1,
            Self::Non(x) => *x as u32 * 3 - 1,

Comment thread src/pratt.rs
Comment on lines +762 to +764
assert!(
parser.parse("§1+-~2!$*3").has_errors(),
);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks a little suspicious. Does this addition change the behaviour of existing parsers?

@NomAnor
Copy link
Copy Markdown
Contributor

NomAnor commented May 18, 2025

Any progress?
I stumbled on the same problem for == and was about to create an issue when I found this PR.

@zesterer
Copy link
Copy Markdown
Owner

Any progress? I stumbled on the same problem for == and was about to create an issue when I found this PR.

Another PR has been opened, but discussion is stale (and probably needs rebasing on upstream). If you're interested in picking it up again, I'd really appreciate it!

@zesterer zesterer force-pushed the main branch 5 times, most recently from 38bb88c to 02a1373 Compare May 26, 2025 14:11
@zesterer zesterer force-pushed the main branch 2 times, most recently from 0f2b61a to e350fc6 Compare November 5, 2025 19:21
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants