@@ -3789,7 +3789,13 @@ impl<'a> Parser<'a> {
3789
3789
self . span_err ( self . last_span , message) ;
3790
3790
}
3791
3791
3792
- /// Parse a statement. may include decl.
3792
+ /// Parse a statement. This stops just before trailing semicolons on everything but items.
3793
+ /// e.g. a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
3794
+ ///
3795
+ /// Also, if a macro begins an expression statement, this only parses the macro. For example,
3796
+ /// ```rust
3797
+ /// vec![1].into_iter(); //< `parse_stmt` only parses the "vec![1]"
3798
+ /// ```
3793
3799
pub fn parse_stmt ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3794
3800
Ok ( self . parse_stmt_ ( ) )
3795
3801
}
@@ -4038,36 +4044,14 @@ impl<'a> Parser<'a> {
4038
4044
let mut stmts = vec ! [ ] ;
4039
4045
4040
4046
while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
4041
- let Stmt { node , span , .. } = if let Some ( s ) = self . parse_stmt_ ( ) {
4042
- s
4047
+ if let Some ( stmt ) = self . parse_stmt_ ( ) {
4048
+ stmts . push ( self . finish_parsing_statement ( stmt ) ? ) ;
4043
4049
} else if self . token == token:: Eof {
4044
4050
break ;
4045
4051
} else {
4046
4052
// Found only `;` or `}`.
4047
4053
continue ;
4048
4054
} ;
4049
-
4050
- match node {
4051
- StmtKind :: Expr ( e) => {
4052
- self . handle_expression_like_statement ( e, span, & mut stmts) ?;
4053
- }
4054
- StmtKind :: Mac ( mac) => {
4055
- self . handle_macro_in_block ( mac. unwrap ( ) , span, & mut stmts) ?;
4056
- }
4057
- _ => { // all other kinds of statements:
4058
- let mut hi = span. hi ;
4059
- if classify:: stmt_ends_with_semi ( & node) {
4060
- self . expect ( & token:: Semi ) ?;
4061
- hi = self . last_span . hi ;
4062
- }
4063
-
4064
- stmts. push ( Stmt {
4065
- id : ast:: DUMMY_NODE_ID ,
4066
- node : node,
4067
- span : mk_sp ( span. lo , hi)
4068
- } ) ;
4069
- }
4070
- }
4071
4055
}
4072
4056
4073
4057
Ok ( P ( ast:: Block {
@@ -4078,93 +4062,50 @@ impl<'a> Parser<'a> {
4078
4062
} ) )
4079
4063
}
4080
4064
4081
- fn handle_macro_in_block ( & mut self ,
4082
- ( mac, style, attrs) : ( ast:: Mac , MacStmtStyle , ThinVec < Attribute > ) ,
4083
- span : Span ,
4084
- stmts : & mut Vec < Stmt > )
4085
- -> PResult < ' a , ( ) > {
4086
- if style == MacStmtStyle :: NoBraces {
4087
- // statement macro without braces; might be an
4088
- // expr depending on whether a semicolon follows
4089
- match self . token {
4090
- token:: Semi => {
4091
- stmts. push ( Stmt {
4092
- id : ast:: DUMMY_NODE_ID ,
4093
- node : StmtKind :: Mac ( P ( ( mac, MacStmtStyle :: Semicolon , attrs) ) ) ,
4094
- span : mk_sp ( span. lo , self . span . hi ) ,
4095
- } ) ;
4096
- self . bump ( ) ;
4097
- }
4098
- _ => {
4099
- let e = self . mk_mac_expr ( span. lo , span. hi , mac. node , ThinVec :: new ( ) ) ;
4100
- let lo = e. span . lo ;
4101
- let e = self . parse_dot_or_call_expr_with ( e, lo, attrs) ?;
4102
- let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
4103
- self . handle_expression_like_statement ( e, span, stmts) ?;
4104
- }
4105
- }
4106
- } else {
4107
- // statement macro; might be an expr
4108
- match self . token {
4109
- token:: Semi => {
4110
- stmts. push ( Stmt {
4111
- id : ast:: DUMMY_NODE_ID ,
4112
- node : StmtKind :: Mac ( P ( ( mac, MacStmtStyle :: Semicolon , attrs) ) ) ,
4113
- span : mk_sp ( span. lo , self . span . hi ) ,
4114
- } ) ;
4115
- self . bump ( ) ;
4116
- }
4117
- _ => {
4118
- stmts. push ( Stmt {
4119
- id : ast:: DUMMY_NODE_ID ,
4120
- node : StmtKind :: Mac ( P ( ( mac, style, attrs) ) ) ,
4121
- span : span
4122
- } ) ;
4123
- }
4065
+ /// Finish parsing expressions that start with macros and handle trailing semicolons
4066
+ /// (or the lack thereof) -- c.f. `parse_stmt`.
4067
+ fn finish_parsing_statement ( & mut self , mut stmt : Stmt ) -> PResult < ' a , Stmt > {
4068
+ if let StmtKind :: Mac ( mac) = stmt. node {
4069
+ if mac. 1 != MacStmtStyle :: NoBraces || self . token == token:: Semi {
4070
+ stmt. node = StmtKind :: Mac ( mac) ;
4071
+ } else {
4072
+ let ( mac, _style, attrs) = mac. unwrap ( ) ;
4073
+ let e = self . mk_mac_expr ( stmt. span . lo , stmt. span . hi , mac. node , ThinVec :: new ( ) ) ;
4074
+ let e = self . parse_dot_or_call_expr_with ( e, stmt. span . lo , attrs) ?;
4075
+ let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
4076
+ stmt. node = StmtKind :: Expr ( e) ;
4124
4077
}
4125
4078
}
4126
- Ok ( ( ) )
4079
+
4080
+ self . handle_trailing_semicolon ( stmt)
4127
4081
}
4128
4082
4129
- fn handle_expression_like_statement ( & mut self ,
4130
- e : P < Expr > ,
4131
- span : Span ,
4132
- stmts : & mut Vec < Stmt > )
4133
- -> PResult < ' a , ( ) > {
4134
- // expression without semicolon
4135
- if classify :: expr_requires_semi_to_be_stmt ( & e) {
4136
- // Just check for errors and recover; do not eat semicolon yet.
4137
- if let Err ( mut e ) =
4138
- self . expect_one_of ( & [ ] , & [ token :: Semi , token :: CloseDelim ( token :: Brace ) ] )
4139
- {
4140
- e . emit ( ) ;
4141
- self . recover_stmt ( ) ;
4083
+ fn handle_trailing_semicolon ( & mut self , mut stmt : Stmt ) -> PResult < ' a , Stmt > {
4084
+ match stmt . node {
4085
+ StmtKind :: Expr ( ref expr ) => {
4086
+ // expression without semicolon
4087
+ if classify :: expr_requires_semi_to_be_stmt ( expr ) {
4088
+ // Just check for errors and recover; do not eat semicolon yet.
4089
+ if let Err ( mut e) =
4090
+ self . expect_one_of ( & [ ] , & [ token :: Semi , token :: CloseDelim ( token :: Brace ) ] )
4091
+ {
4092
+ e . emit ( ) ;
4093
+ self . recover_stmt ( ) ;
4094
+ }
4095
+ }
4142
4096
}
4097
+ StmtKind :: Local ( ..) => {
4098
+ self . expect_one_of ( & [ token:: Semi ] , & [ ] ) ?;
4099
+ }
4100
+ _ => { }
4143
4101
}
4144
4102
4145
- match self . token {
4146
- token:: Semi => {
4147
- self . bump ( ) ;
4148
- let span_with_semi = Span {
4149
- lo : span. lo ,
4150
- hi : self . last_span . hi ,
4151
- expn_id : span. expn_id ,
4152
- } ;
4153
- stmts. push ( Stmt {
4154
- id : ast:: DUMMY_NODE_ID ,
4155
- node : StmtKind :: Semi ( e) ,
4156
- span : span_with_semi,
4157
- } ) ;
4158
- }
4159
- _ => {
4160
- stmts. push ( Stmt {
4161
- id : ast:: DUMMY_NODE_ID ,
4162
- node : StmtKind :: Expr ( e) ,
4163
- span : span
4164
- } ) ;
4165
- }
4103
+ if self . eat ( & token:: Semi ) {
4104
+ stmt = stmt. add_trailing_semicolon ( ) ;
4166
4105
}
4167
- Ok ( ( ) )
4106
+
4107
+ stmt. span . hi = self . last_span . hi ;
4108
+ Ok ( stmt)
4168
4109
}
4169
4110
4170
4111
// Parses a sequence of bounds if a `:` is found,
0 commit comments