about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorA C <achan1989@gmail.com>2019-09-16 21:45:43 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2019-12-20 22:41:29 +0100
commit0c32ee17815ee2ba77e44045f89c19a46580c785 (patch)
treeaabe5241453e801d3a6ce4417fb0d9d113884c60 /src
parent0b7908c550a2db5358a6d82a5bbc93a5fff4cec5 (diff)
downloadrust-0c32ee17815ee2ba77e44045f89c19a46580c785.tar.gz
rust-0c32ee17815ee2ba77e44045f89c19a46580c785.zip
Clean up `parse_bottom_expr`
Diffstat (limited to 'src')
-rw-r--r--src/librustc_parse/parser/expr.rs99
1 files changed, 39 insertions, 60 deletions
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 7af9b7267a8..1033a815985 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -91,24 +91,29 @@ impl<'a> Parser<'a> {
         self.parse_expr_res(Restrictions::empty(), None)
     }
 
+    fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
+        match self.parse_expr() {
+            Ok(expr) => Ok(expr),
+            Err(mut err) => match self.token.kind {
+                token::Ident(name, false)
+                if name == kw::Underscore && self.look_ahead(1, |t| {
+                    t == &token::Comma
+                }) => {
+                    // Special-case handling of `foo(_, _, _)`
+                    err.emit();
+                    let sp = self.token.span;
+                    self.bump();
+                    Ok(self.mk_expr(sp, ExprKind::Err, ThinVec::new()))
+                }
+                _ => Err(err),
+            },
+        }
+    }
+
+    /// Parses a sequence of expressions bounded by parentheses.
     fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
         self.parse_paren_comma_seq(|p| {
-            match p.parse_expr() {
-                Ok(expr) => Ok(expr),
-                Err(mut err) => match p.token.kind {
-                    token::Ident(name, false)
-                    if name == kw::Underscore && p.look_ahead(1, |t| {
-                        t == &token::Comma
-                    }) => {
-                        // Special-case handling of `foo(_, _, _)`
-                        err.emit();
-                        let sp = p.token.span;
-                        p.bump();
-                        Ok(p.mk_expr(sp, ExprKind::Err, ThinVec::new()))
-                    }
-                    _ => Err(err),
-                },
-            }
+            p.parse_expr_catch_underscore()
         }).map(|(r, _)| r)
     }
 
@@ -845,51 +850,25 @@ impl<'a> Parser<'a> {
                 parse_lit!()
             }
             token::OpenDelim(token::Paren) => {
-                self.bump();
-
-                attrs.extend(self.parse_inner_attributes()?);
-
-                // `(e)` is parenthesized `e`.
-                // `(e,)` is a tuple with only one field, `e`.
-                let mut es = vec![];
-                let mut trailing_comma = false;
-                let mut recovered = false;
-                while self.token != token::CloseDelim(token::Paren) {
-                    es.push(match self.parse_expr() {
-                        Ok(es) => es,
-                        Err(mut err) => {
-                            // Recover from parse error in tuple list.
-                            match self.token.kind {
-                                token::Ident(name, false)
-                                if name == kw::Underscore && self.look_ahead(1, |t| {
-                                    t == &token::Comma
-                                }) => {
-                                    // Special-case handling of `Foo<(_, _, _)>`
-                                    err.emit();
-                                    let sp = self.token.span;
-                                    self.bump();
-                                    self.mk_expr(sp, ExprKind::Err, ThinVec::new())
-                                }
-                                _ => return Ok(
-                                    self.recover_seq_parse_error(token::Paren, lo, Err(err)),
-                                ),
-                            }
-                        }
-                    });
-                    recovered = self.expect_one_of(
-                        &[],
-                        &[token::Comma, token::CloseDelim(token::Paren)],
-                    )?;
-                    if self.eat(&token::Comma) {
-                        trailing_comma = true;
-                    } else {
-                        trailing_comma = false;
-                        break;
+                let mut first = true;
+                let parse_leading_attr_expr = |this: &mut Parser<'a>| {
+                    if first {
+                        attrs.extend(this.parse_inner_attributes()?);
+                        first = false;
                     }
-                }
-                if !recovered {
-                    self.bump();
-                }
+                    this.parse_expr_catch_underscore()
+                };
+
+                // (e) is parenthesized e
+                // (e,) is a tuple with only one field, e
+                let (es, trailing_comma) =
+                    match self.parse_paren_comma_seq(parse_leading_attr_expr)
+                {
+                    Ok(x) => x,
+                    Err(err) => return Ok(
+                        self.recover_seq_parse_error(token::Paren, lo, Err(err)),
+                    ),
+                };
 
                 hi = self.prev_span;
                 ex = if es.len() == 1 && !trailing_comma {