diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-05-15 16:03:22 +0200 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-06-23 01:29:29 +0200 |
| commit | dff1e379fc55429ea9a4794634e02c17cebee603 (patch) | |
| tree | 4ec38d68cd0186eebcfba9d20144d43e742a0a74 /src/libsyntax | |
| parent | 3fc964201486f9fdb006bfb7d0caf9b1c3e6cb71 (diff) | |
| download | rust-dff1e379fc55429ea9a4794634e02c17cebee603.tar.gz rust-dff1e379fc55429ea9a4794634e02c17cebee603.zip | |
let_chains: Add support for parsing let expressions.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 67 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/util/parser.rs | 7 |
3 files changed, 22 insertions, 53 deletions
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::<Vec<_>>(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<Attribute>) -> PResult<'a, P<Expr>> { - 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<Attribute>) - -> PResult<'a, P<Expr>> { + /// Parses a `let $pats = $expr` pseudo-expression. + /// The `let` token has already been eaten. + fn parse_let_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { 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<Label>, span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { - if self.token.is_keyword(kw::Let) { - return self.parse_while_let_expr(opt_label, span_lo, attrs); - } let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); @@ -3309,20 +3292,6 @@ impl<'a> Parser<'a> { return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs)); } - /// Parses a `while let` expression (`while` token already eaten). - fn parse_while_let_expr(&mut self, opt_label: Option<Label>, - span_lo: Span, - mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { - 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 (iattrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(iattrs); - let span = span_lo.to(body.span); - return Ok(self.mk_expr(span, ExprKind::WhileLet(pats, expr, body, opt_label), attrs)); - } - // parse `loop {...}`, `loop` token already eaten fn parse_loop_expr(&mut self, opt_label: Option<Label>, span_lo: Span, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index cc34883e2e8..98e06ad73c9 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -134,6 +134,7 @@ pub(crate) fn ident_can_begin_expr(name: ast::Name, span: Span, is_raw: bool) -> kw::Continue, kw::False, kw::For, + kw::Let, kw::If, kw::Loop, kw::Match, diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index fcecee8c57f..81b5b085937 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -260,6 +260,7 @@ pub enum ExprPrecedence { Box, AddrOf, + Let, Unary, Call, @@ -277,9 +278,7 @@ pub enum ExprPrecedence { Path, Paren, If, - IfLet, While, - WhileLet, ForLoop, Loop, Match, @@ -318,6 +317,8 @@ impl ExprPrecedence { // Unary, prefix ExprPrecedence::Box | ExprPrecedence::AddrOf | + // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`. + ExprPrecedence::Let | ExprPrecedence::Unary => PREC_PREFIX, // Unary, postfix @@ -338,9 +339,7 @@ impl ExprPrecedence { ExprPrecedence::Path | ExprPrecedence::Paren | ExprPrecedence::If | - ExprPrecedence::IfLet | ExprPrecedence::While | - ExprPrecedence::WhileLet | ExprPrecedence::ForLoop | ExprPrecedence::Loop | ExprPrecedence::Match | |
