Skip to content

Commit 58c299f

Browse files
committed
Fix prefix range expressions being not parsed
1 parent 884b589 commit 58c299f

File tree

2 files changed

+77
-74
lines changed

2 files changed

+77
-74
lines changed

src/libsyntax/parse/parser.rs

+68-74
Original file line numberDiff line numberDiff line change
@@ -2602,53 +2602,50 @@ impl<'a> Parser<'a> {
26022602
pub fn parse_prefix_expr(&mut self) -> PResult<P<Expr>> {
26032603
let lo = self.span.lo;
26042604
let hi;
2605-
26062605
// Note: when adding new unary operators, don't forget to adjust Token::can_begin_expr()
2607-
let ex;
2608-
match self.token {
2609-
token::Not => {
2610-
try!(self.bump());
2611-
let e = try!(self.parse_prefix_expr());
2612-
hi = e.span.hi;
2613-
ex = self.mk_unary(UnNot, e);
2614-
}
2615-
token::BinOp(token::Minus) => {
2616-
try!(self.bump());
2617-
let e = try!(self.parse_prefix_expr());
2618-
hi = e.span.hi;
2619-
ex = self.mk_unary(UnNeg, e);
2620-
}
2621-
token::BinOp(token::Star) => {
2622-
try!(self.bump());
2623-
let e = try!(self.parse_prefix_expr());
2624-
hi = e.span.hi;
2625-
ex = self.mk_unary(UnDeref, e);
2626-
}
2627-
token::BinOp(token::And) | token::AndAnd => {
2628-
try!(self.expect_and());
2629-
let m = try!(self.parse_mutability());
2630-
let e = try!(self.parse_prefix_expr());
2631-
hi = e.span.hi;
2632-
ex = ExprAddrOf(m, e);
2633-
}
2634-
token::Ident(..) if self.token.is_keyword(keywords::In) => {
2635-
try!(self.bump());
2636-
let place = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
2637-
let blk = try!(self.parse_block());
2638-
let span = blk.span;
2639-
hi = span.hi;
2640-
let blk_expr = self.mk_expr(span.lo, span.hi, ExprBlock(blk));
2641-
self.span_warn(span, "in PLACE BLOCK syntax is deprecated and will be removed soon");
2642-
ex = ExprInPlace(place, blk_expr);
2643-
}
2644-
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
2645-
try!(self.bump());
2646-
let subexpression = try!(self.parse_prefix_expr());
2647-
hi = subexpression.span.hi;
2648-
ex = ExprBox(subexpression);
2649-
}
2650-
_ => return self.parse_dot_or_call_expr()
2651-
}
2606+
let ex = match self.token {
2607+
token::Not => {
2608+
try!(self.bump());
2609+
let e = try!(self.parse_prefix_expr());
2610+
hi = e.span.hi;
2611+
self.mk_unary(UnNot, e)
2612+
}
2613+
token::BinOp(token::Minus) => {
2614+
try!(self.bump());
2615+
let e = try!(self.parse_prefix_expr());
2616+
hi = e.span.hi;
2617+
self.mk_unary(UnNeg, e)
2618+
}
2619+
token::BinOp(token::Star) => {
2620+
try!(self.bump());
2621+
let e = try!(self.parse_prefix_expr());
2622+
hi = e.span.hi;
2623+
self.mk_unary(UnDeref, e)
2624+
}
2625+
token::BinOp(token::And) | token::AndAnd => {
2626+
try!(self.expect_and());
2627+
let m = try!(self.parse_mutability());
2628+
let e = try!(self.parse_prefix_expr());
2629+
hi = e.span.hi;
2630+
ExprAddrOf(m, e)
2631+
}
2632+
token::Ident(..) if self.token.is_keyword(keywords::In) => {
2633+
try!(self.bump());
2634+
let place = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
2635+
let blk = try!(self.parse_block());
2636+
let span = blk.span;
2637+
hi = span.hi;
2638+
let blk_expr = self.mk_expr(span.lo, span.hi, ExprBlock(blk));
2639+
ExprInPlace(place, blk_expr)
2640+
}
2641+
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
2642+
try!(self.bump());
2643+
let subexpression = try!(self.parse_prefix_expr());
2644+
hi = subexpression.span.hi;
2645+
ExprBox(subexpression)
2646+
}
2647+
_ => return self.parse_dot_or_call_expr()
2648+
};
26522649
return Ok(self.mk_expr(lo, hi, ex));
26532650
}
26542651

@@ -2657,35 +2654,15 @@ impl<'a> Parser<'a> {
26572654
/// This parses an expression accounting for associativity and precedence of the operators in
26582655
/// the expression.
26592656
pub fn parse_assoc_expr(&mut self) -> PResult<P<Expr>> {
2660-
if self.token == token::DotDot {
2661-
// prefix-form of range notation `..expr` and `..`
2662-
// This has the precedence just higher than assignment expressions (much lower than
2663-
// other prefix expressions) to be consistent with the postfix-form `expr..`
2664-
// If it isn’t clear yet, this is a hack of the worst kind (one that also probably
2665-
// can’t be fixed anymore because stability guarantees).
2666-
let lo = self.span.lo;
2667-
let mut hi = self.span.hi;
2668-
try!(self.bump());
2669-
let opt_end = if self.is_at_start_of_range_notation_rhs() {
2670-
// RHS must be parsed with more associativity than DotDot.
2671-
let next_prec = AssocOp::from_token(&token::DotDot).unwrap().precedence() + 1;
2672-
let end = try!(self.parse_assoc_expr_with(next_prec, None));
2673-
hi = end.span.hi;
2674-
Some(end)
2675-
} else {
2676-
None
2677-
};
2678-
let r = self.mk_range(None, opt_end);
2679-
Ok(self.mk_expr(lo, hi, r))
2680-
} else {
2681-
self.parse_assoc_expr_with(0, None)
2682-
}
2657+
self.parse_assoc_expr_with(0, None)
26832658
}
26842659

26852660
/// Parse an associative expression with operators of at least `min_prec` precedence
26862661
pub fn parse_assoc_expr_with(&mut self, min_prec: usize, lhs: Option<P<Expr>>) -> PResult<P<Expr>> {
26872662
let mut lhs = if lhs.is_some() {
26882663
lhs.unwrap()
2664+
} else if self.token == token::DotDot {
2665+
return self.parse_prefix_range_expr();
26892666
} else {
26902667
try!(self.parse_prefix_expr())
26912668
};
@@ -2710,13 +2687,10 @@ impl<'a> Parser<'a> {
27102687
continue
27112688
} else if op == AssocOp::DotDot {
27122689
// If we didn’t have to handle `x..`, it would be pretty easy to generalise
2713-
// here by simply doing something along the lines of
2714-
//
2715-
// break_from_this_loop_after_setting_lhs = true;
2716-
// rhs = self.parse_assoc_expr_with(op.precedence() + 1, None);
2690+
// it to the Fixity::None code.
27172691
//
27182692
// We have 2 alternatives here: `x..y` and `x..` The other two variants are
2719-
// handled in `parse_assoc_expr`
2693+
// handled with `parse_prefix_range_expr` call above.
27202694
let rhs = if self.is_at_start_of_range_notation_rhs() {
27212695
self.parse_assoc_expr_with(op.precedence() + 1, None).ok()
27222696
} else {
@@ -2800,6 +2774,26 @@ impl<'a> Parser<'a> {
28002774
}
28012775
}
28022776

2777+
/// Parse prefix-forms of range notation: `..expr` and `..`
2778+
fn parse_prefix_range_expr(&mut self) -> PResult<P<Expr>> {
2779+
debug_assert!(self.token == token::DotDot);
2780+
let lo = self.span.lo;
2781+
let mut hi = self.span.hi;
2782+
try!(self.bump());
2783+
let opt_end = if self.is_at_start_of_range_notation_rhs() {
2784+
// RHS must be parsed with more associativity than DotDot.
2785+
let next_prec = AssocOp::from_token(&token::DotDot).unwrap().precedence() + 1;
2786+
Some(try!(self.parse_assoc_expr_with(next_prec, None).map(|x|{
2787+
hi = x.span.hi;
2788+
x
2789+
})))
2790+
} else {
2791+
None
2792+
};
2793+
let r = self.mk_range(None, opt_end);
2794+
Ok(self.mk_expr(lo, hi, r))
2795+
}
2796+
28032797
fn is_at_start_of_range_notation_rhs(&self) -> bool {
28042798
if self.token.can_begin_expr() {
28052799
// parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.

src/libsyntax/util/parser.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
110
use parse::token::{Token, BinOpToken, keywords};
211
use ast;
312

0 commit comments

Comments
 (0)