tree-sitter-c-sharp
tree-sitter-c-sharp copied to clipboard
Incorrect precedence in conditional_access_expression
var a = b?.Something?.Something;
Actual:
(equals_value_clause [6, 14] - [6, 39]
(conditional_access_expression [6, 16] - [6, 39]
(conditional_access_expression [6, 16] - [6, 28]
(identifier [6, 16] - [6, 17])
(member_binding_expression [6, 18] - [6, 28]
(identifier [6, 19] - [6, 28])))
(member_binding_expression [6, 29] - [6, 39]
(identifier [6, 30] - [6, 39]))))))))))))
Expected:
(equals_value_clause [6, 14] - [6, 39]
(conditional_access_expression [6, 16] - [6, 39]
(identifier [6, 16] - [6, 17])
(conditional_access_expression [6, 18] - [6, 39]
(member_binding_expression [6, 18] - [6, 28]
(identifier [6, 19] - [6, 28]))
(member_binding_expression [6, 29] - [6, 39]
(identifier [6, 30] - [6, 39])))))))))))))
Other issues related to conditional access expressions are #131, #138, #151, #173.
Test case:
=====================================
Conditional access expression is right-associative
=====================================
var a = b?.Something?.Something;
---
(compilation_unit
(global_statement
(local_declaration_statement
(variable_declaration
(implicit_type)
(variable_declarator
(identifier)
(equals_value_clause
(conditional_access_expression
(identifier)
(conditional_access_expression
(member_binding_expression
(identifier))
(member_binding_expression
(identifier))))))))))
I thought conditional access expressions should be right-associative because:
- Roslyn parses it this way.
- The grammar specifies
prec.rightin conditional_access_expression.
However, whether it is left or right associative may not make much of a functional difference. I can't think of a situation where using left-associativity would give another result to an expression. So this may not really be a big problem.
I think the problems with conditional access are related to this issue: Adding a rule changes associativity from right to left · Issue #1301 · tree-sitter/tree-sitter
Conditional access expressions conflict with the conditional ternary operator.
a || a ? .b
a || a ? true : false
If the parser sees a || a ?, it doesn't know whether to reduce a || a into an expr or keep parsing. Currently, it reduces. This is correct for the conditional ternary operator, but incorrect for the conditional access expression.
@maxbrunsfeld have you got any ideas how we could tackle this one?
If the parser sees a || a ?, it doesn't know whether to reduce a || a into an expr or keep parsing.
I think it can't know with just one lookahead token.
In a || a · ?, the ? is one token lookahead, but that is insufficient information do determine whether to reduce a || a or not. We need to lookahead further, to find out whether the ? is part of ? expr : expr or ?. expr. This can be done with an external scanner. An external scanner can lookahead further, but it adds complexity. Particularly because it also should skip comments/extras.