Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1169

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176
8000 Add non-associative infix operators by NomAnor · Pull Request #800 · zesterer/chumsky · GitHub
Nothing Special   »   [go: up one dir, main page]

Skip to content

Conversation

NomAnor
Copy link
Contributor
@NomAnor NomAnor commented May 22, 2025

I tried to mess with the code and got a working solution. I'm new to rust, so this might not be the best code.

I had to disallow a precedence of zero, which might be a breaking change. Zero is used as a start marker
and all implementations I've seen use precedences > 0 when defining the operators.

I also switched the check for associtivity with the operator parsing, which might change the performance?

Now the test pratt::tests::with_pre_and_postfix_ops fails because it contains an ambiguity between the § and + operator, both have a binding power of 4.
The comment in that test case indicates that such ambiguity is not a good thing, so maybe this new behaviour is okay? Then the check could just be changed. The old behaviour bound infix operators tighter than prefix operators of the same precedence.

This is a new attempt, the other ones are #600 and #728.

Copy link
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.

This is very cool, thanks so much for your work! I've just a small suggestion above.

Additionally, I'm wondering whether we could avoid breaking binding powers of 0 by casting the u16 up to a i32 and using i32::MIN as the starting marker?

src/pratt.rs Outdated
pub fn right(binding_power: u16) -> Associativity {
Associativity::Right(binding_power)
pub fn right(precedence: u16) -> Associativity {
assert!(precedence > 0);
Copy link
Owner

Choose a reason for hiding this comment

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

Might be worth adding #[track_caller] to this function (and others), which should result in the assert location pointing to the caller location rather than inside the function.

@zesterer
Copy link
Owner

Hmm, looks like there are CI failures too.

NomAnor added 4 commits May 25, 2025 11:52
Binding power is an implementation detail, what users specify
is the precedence level.
The binding power zero is used as a special marker for the first
invocation.
User can specify a precedence of zero resulting in a binding power
of zero, which would mimic this marker.

Use an i32 and i32:MIN as a marker instead.
This designates an infox operator as non-associative.
Chained operator result in a parse error because without an
associativity they can't be unambigiously parsed.

Also add some test cases that will fail for now.
All pratt operators can now return two types of errors,
non-fatal (`NoMatch`), which allow the parse to continue and
fatal (`Err`) errors, that abort the parse.

If a non-associative infix operator encounters an operator with
the same binding strength it returns a fatal error because of
an ambigious input.

For this to work, the infix operator mus first parse it's operator
before checking the binding power.
@NomAnor NomAnor force-pushed the non-associative branch from cacbd20 to 17985a4 Compare May 25, 2025 09:52
@NomAnor
Copy link
Contributor Author
NomAnor commented May 25, 2025

Additionally, I'm wondering whether we could avoid breaking binding powers of 0 by casting the u16 up to a i32 and using i32::MIN as the starting marker?

I changed it, a precedence of zero is now ok.

Hmm, looks like there are CI failures too.

The check failures are somwhere else in the code, not sure why they fail.
The semver check seems to file because I didn't bump the version, but should this not be done on release?
The test failure is because of the pratt::tests::with_pre_and_postfix_ops test.

I made the new result type more generic so every operator can use it. I don't know how to handle error reporting properly. The infix parse returns a fatal error if it finds an operator (non-associative) with the same precedence. This is an ambigious input and should ideally result an an error like "Ambigous operator order, use () to fix it" or something like that.
But these error message should be provided by the user and I don't see how to allow that.

The above test fails because the prefix operator "§" and the infix operator "+" have the same binding_power, but "+" is non-associative. I think this should not cause an error because associativity should onyl matter between infix operators. I have to think how to fix that.

@NomAnor
Copy link
Contributor Author
NomAnor commented May 25, 2025

I have to think how to fix that.

Got it, just need to check if the operator is actually non-associative.

What do you thing about the error handling/message?

@zesterer
Copy link
Owner
zesterer commented May 25, 2025

Got it, just need to check if the operator is actually non-associative.

Great!

What do you thing about the error handling/message?

I think this is fine for an initial implementation. That said, chumsky supports non-fatal errors. It should be possible for the pratt parser to successfully generate an output while also emitting an error about the use of non-associative operators. You can find an example of this being doing in the validate combinator. You can probably add a new method to LabelError (with a default implementation) for non-associative errors: maybe it could take the spans of the two operators or something?

What do you think?

@zesterer zesterer force-pushed the main branch 5 times, most recently from 38bb88c to 02a1373 Compare May 26, 2025 14:11
@NomAnor NomAnor marked this pull request as ready for review June 15, 2025 12:28
@NomAnor
Copy link
Contributor Author
NomAnor commented Jun 15, 2025

I haven't wrapped my head around the error handling. If I need to use it in my code, I might come back to it.
For now I think the base functionality is there.

@zesterer zesterer merged commit eb0966a into zesterer:main Jun 17, 2025
2 of 4 checks passed
@zesterer
Copy link
Owner

Thanks! I may make some minor modifications to this post-merge, but I really appreciate all of the work you've put into this!

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

Successfully merging this pull request may close these issues.

2 participants

0