From dff1e379fc55429ea9a4794634e02c17cebee603 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 15 May 2019 16:03:22 +0200 Subject: let_chains: Add support for parsing let expressions. --- src/libsyntax/parse/parser.rs | 67 ++++++++++++------------------------------- src/libsyntax/parse/token.rs | 1 + 2 files changed, 19 insertions(+), 49 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fa697e06d26..8cf05059e8a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2215,13 +2215,8 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Yield(None); } - } else if self.token.is_keyword(kw::Let) { - // Catch this syntax error here, instead of in `parse_ident`, so - // that we can explicitly mention that let is not to be used as an expression - let mut db = self.fatal("expected expression, found statement (`let`)"); - db.span_label(self.token.span, "expected expression"); - db.note("variable declaration using `let` is a statement"); - return Err(db); + } else if self.eat_keyword(kw::Let) { + return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { let (await_hi, e_kind) = self.parse_await_macro_or_alt(lo, self.prev_span)?; hi = await_hi; @@ -2483,15 +2478,13 @@ impl<'a> Parser<'a> { attrs.extend::>(expr.attrs.into()); expr.attrs = attrs; match expr.node { - ExprKind::If(..) | ExprKind::IfLet(..) => { - if !expr.attrs.is_empty() { - // Just point to the first attribute in there... - let span = expr.attrs[0].span; - - self.span_err(span, - "attributes are not yet allowed on `if` \ - expressions"); - } + ExprKind::If(..) if !expr.attrs.is_empty() => { + // Just point to the first attribute in there... + let span = expr.attrs[0].span; + + self.span_err(span, + "attributes are not yet allowed on `if` \ + expressions"); } _ => {} } @@ -3163,9 +3156,6 @@ impl<'a> Parser<'a> { /// Parses an `if` or `if let` expression (`if` token already eaten). fn parse_if_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { - if self.check_keyword(kw::Let) { - return self.parse_if_let_expr(attrs); - } let lo = self.prev_span; let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; @@ -3197,22 +3187,18 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs)) } - /// Parses an `if let` expression (`if` token already eaten). - fn parse_if_let_expr(&mut self, attrs: ThinVec) - -> PResult<'a, P> { + /// Parses a `let $pats = $expr` pseudo-expression. + /// The `let` token has already been eaten. + fn parse_let_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; - self.expect_keyword(kw::Let)?; let pats = self.parse_pats()?; self.expect(&token::Eq)?; - let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; - let thn = self.parse_block()?; - let (hi, els) = if self.eat_keyword(kw::Else) { - let expr = self.parse_else_expr()?; - (expr.span, Some(expr)) - } else { - (thn.span, None) - }; - Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs)) + + let expr = self.with_res( + Restrictions::NO_STRUCT_LITERAL, + |this| this.parse_assoc_expr_with(1 + AssocOp::LAnd.precedence(), None.into()) + )?; + Ok(self.mk_expr(lo.to(expr.span), ExprKind::Let(pats, expr), attrs)) } /// Parses `move |args| expr`. @@ -3299,9 +3285,6 @@ impl<'a> Parser<'a> { fn parse_while_expr(&mut self, opt_label: Option