refactor assoc op parsing
This commit is contained in:
parent
e43a7ef1d4
commit
05c26a445b
1 changed files with 31 additions and 20 deletions
|
|
@ -210,30 +210,12 @@ impl<'a> Parser<'a> {
|
|||
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
|
||||
continue;
|
||||
} else if op == AssocOp::Colon {
|
||||
let maybe_path = self.could_ascription_be_path(&lhs.kind);
|
||||
self.last_type_ascription = Some((self.prev_span, maybe_path));
|
||||
|
||||
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
|
||||
self.sess.gated_spans.gate(sym::type_ascription, lhs.span);
|
||||
lhs = self.parse_assoc_op_ascribe(lhs, lhs_span)?;
|
||||
continue;
|
||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
||||
// If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
|
||||
// generalise it to the Fixity::None code.
|
||||
//
|
||||
// We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
|
||||
// two variants are handled with `parse_prefix_range_expr` call above.
|
||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||
Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let (lhs_span, rhs_span) =
|
||||
(lhs.span, if let Some(ref x) = rhs { x.span } else { cur_op_span });
|
||||
let limits =
|
||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
||||
|
||||
let r = self.mk_range(Some(lhs), rhs, limits)?;
|
||||
lhs = self.mk_expr(lhs_span.to(rhs_span), r, AttrVec::new());
|
||||
lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -393,6 +375,27 @@ impl<'a> Parser<'a> {
|
|||
&& !classify::expr_requires_semi_to_be_stmt(e)
|
||||
}
|
||||
|
||||
/// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
|
||||
/// The other two variants are handled in `parse_prefix_range_expr` below.
|
||||
fn parse_range_expr(
|
||||
&mut self,
|
||||
prec: usize,
|
||||
lhs: P<Expr>,
|
||||
op: AssocOp,
|
||||
cur_op_span: Span,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||
Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
||||
let span = lhs.span.to(rhs_span);
|
||||
let limits =
|
||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
||||
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new()))
|
||||
}
|
||||
|
||||
fn is_at_start_of_range_notation_rhs(&self) -> bool {
|
||||
if self.token.can_begin_expr() {
|
||||
// Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
|
||||
|
|
@ -615,6 +618,14 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> {
|
||||
let maybe_path = self.could_ascription_be_path(&lhs.kind);
|
||||
self.last_type_ascription = Some((self.prev_span, maybe_path));
|
||||
let lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
|
||||
self.sess.gated_spans.gate(sym::type_ascription, lhs.span);
|
||||
Ok(lhs)
|
||||
}
|
||||
|
||||
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
|
||||
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
self.expect_and()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue