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

Fix inconsistent conflict resolution for try and ternary #75

Merged
merged 1 commit into from
Dec 31, 2021

Conversation

alex-pinkus
Copy link
Owner

@alex-pinkus alex-pinkus commented Dec 31, 2021

In most places in the grammar, we rely on our conflicts resolving
themselves with only one parse interpretation being valid. With try and
ternary, that isn't the case: both of try (foo() ? bar() : baz) and
(try foo()) ? bar() : baz are valid. This matters because bar()
could also be a throws function, and our try is supposed to cover
it.

The rules for dynamic precedence are described here:
tree-sitter/tree-sitter#678

Based on those, it seems like we were getting the correct parse result
in our test cases solely because of some rule definition order, which
"isn't really meant to be relied on." This exposes itself in some
unrelated changes for a custom string interpolation (not included in
this PR) where the rule order changes and flips our interpretation to
the wrong one.

Instead of relying on the ordering behavior, this change tells the
parser to choose try (foo() ? ...) over (try foo()) ? ... by giving
it a dynamic precedence value. This makes our ordering consistent even
in the face of later rule changes.

@alex-pinkus alex-pinkus force-pushed the try-ternary-ambiguity branch from 19bc69b to 1288b4e Compare December 31, 2021 18:16
In most places in the grammar, we rely on our conflicts resolving
themselves with only one parse interpretation being valid. With `try` and
ternary, that isn't the case: both of `try (foo() ? bar() : baz)` and
`(try foo()) ? bar() : baz` are valid. This matters because `bar()`
could also be a `throws` function, and our `try` is supposed to cover
it.

The rules for dynamic precedence are described here:
tree-sitter/tree-sitter#678

Based on those, it seems like we were getting the correct parse result
in our test cases solely because of some rule definition order, which
"isn't really meant to be relied on." This exposes itself in some
unrelated changes for a custom string interpolation (not included in
this PR) where the rule order changes and flips our interpretation to
the wrong one.

Instead of relying on the ordering behavior, this change tells the
parser to choose `try (foo() ? ...)` over `(try foo()) ? ...` by giving
it a dynamic precedence value. This makes our ordering consistent even
in the face of later rule changes.
@alex-pinkus alex-pinkus force-pushed the try-ternary-ambiguity branch from 1288b4e to edd6bdf Compare December 31, 2021 18:17
@alex-pinkus alex-pinkus merged commit b355069 into main Dec 31, 2021
@alex-pinkus alex-pinkus deleted the try-ternary-ambiguity branch December 31, 2021 18:26
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.

1 participant