diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-07-02 09:01:21 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-07-12 04:31:13 +0000 |
| commit | 6189e6cdba6d12ab65baafd95c5f8a6e0cc37937 (patch) | |
| tree | 68ce7a7ccc4d4ca3cc70c10f935a5ecb0055951b /src/libsyntax/parse/parser.rs | |
| parent | 3265bd54b5b3f32d038273afec7554f007a5ce1d (diff) | |
| download | rust-6189e6cdba6d12ab65baafd95c5f8a6e0cc37937.tar.gz rust-6189e6cdba6d12ab65baafd95c5f8a6e0cc37937.zip | |
Clean up statement parsing without changing the semantics of `parse_stmt`.
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 149 |
1 files changed, 45 insertions, 104 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e4875b7c244..0dd8c199827 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3789,7 +3789,13 @@ impl<'a> Parser<'a> { self.span_err(self.last_span, message); } - /// Parse a statement. may include decl. + /// Parse a statement. This stops just before trailing semicolons on everything but items. + /// e.g. a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. + /// + /// Also, if a macro begins an expression statement, this only parses the macro. For example, + /// ```rust + /// vec![1].into_iter(); //< `parse_stmt` only parses the "vec![1]" + /// ``` pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> { Ok(self.parse_stmt_()) } @@ -4038,36 +4044,14 @@ impl<'a> Parser<'a> { let mut stmts = vec![]; while !self.eat(&token::CloseDelim(token::Brace)) { - let Stmt {node, span, ..} = if let Some(s) = self.parse_stmt_() { - s + if let Some(stmt) = self.parse_stmt_() { + stmts.push(self.finish_parsing_statement(stmt)?); } else if self.token == token::Eof { break; } else { // Found only `;` or `}`. continue; }; - - match node { - StmtKind::Expr(e) => { - self.handle_expression_like_statement(e, span, &mut stmts)?; - } - StmtKind::Mac(mac) => { - self.handle_macro_in_block(mac.unwrap(), span, &mut stmts)?; - } - _ => { // all other kinds of statements: - let mut hi = span.hi; - if classify::stmt_ends_with_semi(&node) { - self.expect(&token::Semi)?; - hi = self.last_span.hi; - } - - stmts.push(Stmt { - id: ast::DUMMY_NODE_ID, - node: node, - span: mk_sp(span.lo, hi) - }); - } - } } Ok(P(ast::Block { @@ -4078,93 +4062,50 @@ impl<'a> Parser<'a> { })) } - fn handle_macro_in_block(&mut self, - (mac, style, attrs): (ast::Mac, MacStmtStyle, ThinVec<Attribute>), - span: Span, - stmts: &mut Vec<Stmt>) - -> PResult<'a, ()> { - if style == MacStmtStyle::NoBraces { - // statement macro without braces; might be an - // expr depending on whether a semicolon follows - match self.token { - token::Semi => { - stmts.push(Stmt { - id: ast::DUMMY_NODE_ID, - node: StmtKind::Mac(P((mac, MacStmtStyle::Semicolon, attrs))), - span: mk_sp(span.lo, self.span.hi), - }); - self.bump(); - } - _ => { - let e = self.mk_mac_expr(span.lo, span.hi, mac.node, ThinVec::new()); - let lo = e.span.lo; - let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; - let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; - self.handle_expression_like_statement(e, span, stmts)?; - } - } - } else { - // statement macro; might be an expr - match self.token { - token::Semi => { - stmts.push(Stmt { - id: ast::DUMMY_NODE_ID, - node: StmtKind::Mac(P((mac, MacStmtStyle::Semicolon, attrs))), - span: mk_sp(span.lo, self.span.hi), - }); - self.bump(); - } - _ => { - stmts.push(Stmt { - id: ast::DUMMY_NODE_ID, - node: StmtKind::Mac(P((mac, style, attrs))), - span: span - }); - } + /// Finish parsing expressions that start with macros and handle trailing semicolons + /// (or the lack thereof) -- c.f. `parse_stmt`. + fn finish_parsing_statement(&mut self, mut stmt: Stmt) -> PResult<'a, Stmt> { + if let StmtKind::Mac(mac) = stmt.node { + if mac.1 != MacStmtStyle::NoBraces || self.token == token::Semi { + stmt.node = StmtKind::Mac(mac); + } else { + let (mac, _style, attrs) = mac.unwrap(); + let e = self.mk_mac_expr(stmt.span.lo, stmt.span.hi, mac.node, ThinVec::new()); + let e = self.parse_dot_or_call_expr_with(e, stmt.span.lo, attrs)?; + let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; + stmt.node = StmtKind::Expr(e); } } - Ok(()) + + self.handle_trailing_semicolon(stmt) } - fn handle_expression_like_statement(&mut self, - e: P<Expr>, - span: Span, - stmts: &mut Vec<Stmt>) - -> PResult<'a, ()> { - // expression without semicolon - if classify::expr_requires_semi_to_be_stmt(&e) { - // Just check for errors and recover; do not eat semicolon yet. - if let Err(mut e) = - self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)]) - { - e.emit(); - self.recover_stmt(); + fn handle_trailing_semicolon(&mut self, mut stmt: Stmt) -> PResult<'a, Stmt> { + match stmt.node { + StmtKind::Expr(ref expr) => { + // expression without semicolon + if classify::expr_requires_semi_to_be_stmt(expr) { + // Just check for errors and recover; do not eat semicolon yet. + if let Err(mut e) = + self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)]) + { + e.emit(); + self.recover_stmt(); + } + } } + StmtKind::Local(..) => { + self.expect_one_of(&[token::Semi], &[])?; + } + _ => {} } - match self.token { - token::Semi => { - self.bump(); - let span_with_semi = Span { - lo: span.lo, - hi: self.last_span.hi, - expn_id: span.expn_id, - }; - stmts.push(Stmt { - id: ast::DUMMY_NODE_ID, - node: StmtKind::Semi(e), - span: span_with_semi, - }); - } - _ => { - stmts.push(Stmt { - id: ast::DUMMY_NODE_ID, - node: StmtKind::Expr(e), - span: span - }); - } + if self.eat(&token::Semi) { + stmt = stmt.add_trailing_semicolon(); } - Ok(()) + + stmt.span.hi = self.last_span.hi; + Ok(stmt) } // Parses a sequence of bounds if a `:` is found, |
