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

Fixing ambiguities between template methods and comparisons #267

Merged
merged 3 commits into from
Jun 17, 2024

Conversation

touzeauv
Copy link

@touzeauv touzeauv commented May 20, 2024

This PR aims at fixing parsing of ambiguous expressions as mentioned in issue #231.

Consider for example the following code:

if (x.foo < 0 || bar >= 1)
    break;

This is currently recognized as an assignment ( of template method x.foo<...> to value 1) instead of the logical disjunction of two comparisons.
My understanding is that, for some reason, the prec.right in front of the field_expression's rule in the grammar prevents the parser from forking when "x.foo" is on the stack and forces the parsing of a template method instead.

I thus removed the prec.right annotation and added a conflict between field_expression, template_method and template_type.
In addition, I added a prec.dynamic annotation in front of field_identifier to avoid the reduction to a template method when reducing to a field_identifier is possible.

Note that there exists situation in which both interpretations could be valid, and there is no way to decide which one is correct from the information available to the parser.
An example of this situation is the following:

// Either a call to X::foo<bool> with parameter 5, or a comparison of x.foo to 0 and bar to 5.
bool b = x.foo < 0 || bar > (5);

In this specific case, I think having a binary expression as a template parameter is very unusual and so the dynamic precedence is fine. However, I might have overlook other situations where the template_method interpretation is the correct one.

The same ambiguity appears when the field_identifier is qualified, I thus apply the same modifications to the qualified_field_identifier rule, i.e. removing the prec.right, adding a conflict and forcing the interpretation to a field_identifier using dynamic precedence in case of ambiguity).

Some things to consider before accepting this PR:

  • I am not sure about why prec.right were being used in the first place. Removing them might be a mistake. Maybe they should be moved to somewhere else instead of being removed.
  • I might have overlook other cases where the reduction to template_method is the correct choice.
  • I am not sure about the "value" to use for the dynamic precedence. I used 1 as a default. Should it be higher? Should the magic value be named?
  • I added two conflicts to the grammar [field_expression, template_method, template_type] and [qualified_field_identifier, template_method, template_type] when following indication from 'tree-sitter generate', but I am not sure about the meaning of these lists. Would having a single conflict with all non-terminals (i.e. [field_expression, qualified_field_identifier, template_method, template_type]) make any difference?

@aryx
Copy link
Contributor

aryx commented May 21, 2024

interesting.
@amaanq what do you think?

@jdrouhard
Copy link
Collaborator

LGTM. I'll merge after I look at the grammar a bit closer this afternoon or tomorrow. Thanks!

@jdrouhard jdrouhard merged commit 7ce8946 into tree-sitter:master Jun 17, 2024
4 checks passed
@jdrouhard
Copy link
Collaborator

Thanks again!

@amaanq
Copy link
Member

amaanq commented Jun 20, 2024

Nice, sorry for not seeing this sooner, thank you @touzeauv!

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.

4 participants