-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
range notation (a..b) has weird operator precedence #20811
Comments
I am planning to fix this myself, but I need input on whether to increase the operator precedence so that |
cc @aturon I think this is a candidate for a nomination as well. |
cc @nick29581 |
Nominating. |
May be related to #20830 |
@alexcrichton: That looks like a different bug in the same line of code. |
I agree about the current precedence being wrong, and think that the suggested position is probably good, but I am very wary of the "restriction no dots" rules. Every restriction is a parser bug until proven otherwise, from my POV, and I am not convinced that we need |
@nikomatsakis: I think some kind of parser special case will always be necessary if we want to allow I know this problem from when I tried writing a C# parser using a parser generator. It turns out that the Microsoft C# compiler is a hand-written recursive-descent parser using the shunting yard algorithm to parse binops. But not all C# binops are true binary operators taking two expressions: the I'd prefer if rust does not make the same mistake as C#, so any prefix- and suffix- operators must be forbidden from being used in a context which conflicts with their operator precedence, even if operator precedence is unnecessary to disambiguate the expression. As far as I know, Here's how I imagine the formal grammar:
This means that "^" and "&&" are left-associative; comparison operators don't have any associativity (since RFC 558); and the range expression doesn't have any associativity either. I hope that this can be implemented without using a |
Changing the precedence level as I suggested actually creates new syntactic ambiguities: With my suggestion, it would be ambiguous between I'm starting to think we should keep the precedence as-is, so that |
On Sat, Jan 10, 2015 at 09:56:42AM -0800, Daniel Grunwald wrote:
Can you spell this out a bit more? |
On Sat, Jan 10, 2015 at 01:43:35PM -0800, Daniel Grunwald wrote:
Why is this not just an argument for a more-refined precedence (like, |
True, I guess we can just pick one interpretation and use it.
When I wrote that, I was just concerned about the complexity of having an optional expression in a chain of binops, but I think probably isn't as bad as I initially thought. The only binops that potentially conflict with the initial token in an expression are:
This corresponds to the disambiguation of |
#20921 points out that |
I have an implementation of my suggested precedence + disambigation. I will create a PR once I have done some testing. I was able to eliminate |
I think we may need a special case to handle |
Fixes rust-lang#20811 and rust-lang#20241. Note: this changes the semantics of parse_more_binops() to parse binops with precedence >= min_prec. Previously, it would parse binops with precedence > min_prec.
On Sun, Jan 11, 2015 at 08:21:03AM -0800, Daniel Grunwald wrote:
We do generally have a subset of expression types that appear in |
Yes, I already handled that case in my implementation: https://github.com/rust-lang/rust/pull/20958/files#diff-da9d34ca1d0f6beee2838cf02e07345cR2942 Overview over what my pull request does:
|
Grammar changes: * allow 'for _ in 1..i {}' (fixes rust-lang#20241) * allow 'for _ in 1.. {}' as infinite loop * prevent use of range notation in contexts where only operators of high precedence are expected (fixes rust-lang#20811) Parser code cleanup: * remove RESTRICTION_NO_DOTS * make AS_PREC const and follow naming convention * make min_prec inclusive
This PR is intended as alternative to #20958. It fixes the same grammar inconsistencies, but does not increase the operator precedence of `..`, leaving it at the same level as the assignment operator. For previous discussion, see #20811 and #20958. Grammar changes: * allow `for _ in 1..i {}` (fixes #20241) * allow `for _ in 1.. {}` as infinite loop * prevent use of range notation in contexts where only operators of high precedence are expected (fixes #20811) Parser code cleanup: * remove `RESTRICTION_NO_DOTS` * make `AS_PREC` const and follow naming convention * make `min_prec` inclusive r? nikomatsakis
Grammar changes: * allow 'for _ in 1..i {}' (fixes rust-lang#20241) * allow 'for _ in 1.. {}' as infinite loop * prevent use of range notation in contexts where only operators of high precedence are expected (fixes rust-lang#20811) Parser code cleanup: * remove RESTRICTION_NO_DOTS * make AS_PREC const and follow naming convention * make min_prec inclusive
First off, the operator precedence of
a..b
is extremely low.struct Range
recently got #[derive(Eq)], so people might want to compare a range to an expression in range notation.r == 1..10
parses as(r == 1)..10
. Similarly,1..10 == r
parses as1..(10 == r)
. Both result in type errors.I think there's no good reason for
..
to have a precedence lower than comparisons. I'd suggest to put it in-between the comparison operators and the bitwise operators.But the current implementation gets weirder when we consider the other forms of range notation:
r == 1..
parses as(r == 1)..
, and is a type error (or maybe aRangeFrom<bool>
).But
r == ..1
parses asr == (..1)
, and is a valid range comparison.In the other direction,
..1 == r
parses as..(1 == r)
and is potentially aRangeTo<bool>
.But
1.. == r
is a syntax error (expected one of)
or,
, found==
).This inconsistent with the prefix form.
If we keep the current precedence of
..
(lower than all binops), I think we should disallowr == ..1
. I think this can be implemented easily by using RESTRICTION_NO_DOTS when parsing the RHS of any binop.Also, we should use RESTRICTION_NO_DOTS when parsing the RHS of prefix-version
..expr
-- currently..1..2
is aRangeTo<Range<_>>
, while1..2..3
and1..2..
both are syntax errors.If we increase the precedence, we will need to be careful not to allow code like
1 + ..2
. I think any binop with precedence smaller than that of..
will have to use RESTRICTION_NO_DOTS on the RHS.I also think the implementation can be simplified quite a bit if the prefix
..
wasn't handled inparse_prefix_expr
(as that's only supposed to be used for operators with high precedence), but at the same level as the binary and postfix version (parse_assign_expr
, orparse_binops
if we change the precedence). This would allow us to get rid of RESTRICTION_NO_DOTS and use the normal operator precedence handling instead.The text was updated successfully, but these errors were encountered: