@@ -105,6 +105,12 @@ pub enum ParsePub {
105
105
No ,
106
106
}
107
107
108
+ #[ derive( Clone , Copy , PartialEq ) ]
109
+ pub enum SemiColonMode {
110
+ Break ,
111
+ Ignore ,
112
+ }
113
+
108
114
/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
109
115
/// dropped into the token stream, which happens while parsing the result of
110
116
/// macro expansion). Placement of these is not as complex as I feared it would
@@ -843,7 +849,10 @@ impl<'a> Parser<'a> {
843
849
/// Eat and discard tokens until one of `kets` is encountered. Respects token trees,
844
850
/// passes through any errors encountered. Used for error recovery.
845
851
pub fn eat_to_tokens ( & mut self , kets : & [ & token:: Token ] ) {
846
- self . parse_seq_to_before_tokens ( kets, seq_sep_none ( ) , |p| p. parse_token_tree ( ) ) ;
852
+ self . parse_seq_to_before_tokens ( kets,
853
+ seq_sep_none ( ) ,
854
+ |p| p. parse_token_tree ( ) ,
855
+ |mut e| e. cancel ( ) ) ;
847
856
}
848
857
849
858
/// Parse a sequence, including the closing delimiter. The function
@@ -871,15 +880,18 @@ impl<'a> Parser<'a> {
871
880
-> Vec < T >
872
881
where F : FnMut ( & mut Parser < ' a > ) -> PResult < ' a , T > ,
873
882
{
874
- self . parse_seq_to_before_tokens ( & [ ket] , sep, f)
883
+ self . parse_seq_to_before_tokens ( & [ ket] , sep, f, | mut e| e . emit ( ) )
875
884
}
876
885
877
- pub fn parse_seq_to_before_tokens < T , F > ( & mut self ,
886
+ // `fe` is an error handler.
887
+ fn parse_seq_to_before_tokens < T , F , Fe > ( & mut self ,
878
888
kets : & [ & token:: Token ] ,
879
889
sep : SeqSep ,
880
- mut f : F )
890
+ mut f : F ,
891
+ mut fe : Fe )
881
892
-> Vec < T >
882
893
where F : FnMut ( & mut Parser < ' a > ) -> PResult < ' a , T > ,
894
+ Fe : FnMut ( DiagnosticBuilder )
883
895
{
884
896
let mut first: bool = true ;
885
897
let mut v = vec ! ( ) ;
@@ -889,8 +901,8 @@ impl<'a> Parser<'a> {
889
901
if first {
890
902
first = false ;
891
903
} else {
892
- if let Err ( mut e) = self . expect ( t) {
893
- e . emit ( ) ;
904
+ if let Err ( e) = self . expect ( t) {
905
+ fe ( e ) ;
894
906
break ;
895
907
}
896
908
}
@@ -903,8 +915,8 @@ impl<'a> Parser<'a> {
903
915
904
916
match f ( self ) {
905
917
Ok ( t) => v. push ( t) ,
906
- Err ( mut e) => {
907
- e . emit ( ) ;
918
+ Err ( e) => {
919
+ fe ( e ) ;
908
920
break ;
909
921
}
910
922
}
@@ -1263,7 +1275,7 @@ impl<'a> Parser<'a> {
1263
1275
break ;
1264
1276
}
1265
1277
}
1266
-
1278
+
1267
1279
return Err ( e) ;
1268
1280
}
1269
1281
} ;
@@ -2339,14 +2351,37 @@ impl<'a> Parser<'a> {
2339
2351
2340
2352
while self . token != token:: CloseDelim ( token:: Brace ) {
2341
2353
if self . eat ( & token:: DotDot ) {
2342
- base = Some ( try!( self . parse_expr ( ) ) ) ;
2354
+ match self . parse_expr ( ) {
2355
+ Ok ( e) => {
2356
+ base = Some ( e) ;
2357
+ }
2358
+ Err ( mut e) => {
2359
+ e. emit ( ) ;
2360
+ self . recover_stmt ( ) ;
2361
+ }
2362
+ }
2343
2363
break ;
2344
2364
}
2345
2365
2346
- fields. push ( try!( self . parse_field ( ) ) ) ;
2347
- try!( self . commit_expr ( & fields. last ( ) . unwrap ( ) . expr ,
2348
- & [ token:: Comma ] ,
2349
- & [ token:: CloseDelim ( token:: Brace ) ] ) ) ;
2366
+ match self . parse_field ( ) {
2367
+ Ok ( f) => fields. push ( f) ,
2368
+ Err ( mut e) => {
2369
+ e. emit ( ) ;
2370
+ self . recover_stmt ( ) ;
2371
+ break ;
2372
+ }
2373
+ }
2374
+
2375
+ match self . commit_expr ( & fields. last ( ) . unwrap ( ) . expr ,
2376
+ & [ token:: Comma ] ,
2377
+ & [ token:: CloseDelim ( token:: Brace ) ] ) {
2378
+ Ok ( ( ) ) => { }
2379
+ Err ( mut e) => {
2380
+ e. emit ( ) ;
2381
+ self . recover_stmt ( ) ;
2382
+ break ;
2383
+ }
2384
+ }
2350
2385
}
2351
2386
2352
2387
hi = self . span . hi ;
@@ -2748,6 +2783,7 @@ impl<'a> Parser<'a> {
2748
2783
if let Some ( & sp) = self . open_braces . last ( ) {
2749
2784
err. span_note ( sp, "unclosed delimiter" ) ;
2750
2785
} ;
2786
+
2751
2787
Err ( err)
2752
2788
} ,
2753
2789
/* we ought to allow different depths of unquotation */
@@ -3195,8 +3231,8 @@ impl<'a> Parser<'a> {
3195
3231
fn parse_match_expr ( & mut self , attrs : ThinAttributes ) -> PResult < ' a , P < Expr > > {
3196
3232
let match_span = self . last_span ;
3197
3233
let lo = self . last_span . lo ;
3198
- let discriminant = try!( self . parse_expr_res (
3199
- Restrictions :: RESTRICTION_NO_STRUCT_LITERAL , None ) ) ;
3234
+ let discriminant = try!( self . parse_expr_res ( Restrictions :: RESTRICTION_NO_STRUCT_LITERAL ,
3235
+ None ) ) ;
3200
3236
if let Err ( mut e) = self . commit_expr_expecting ( & discriminant,
3201
3237
token:: OpenDelim ( token:: Brace ) ) {
3202
3238
if self . token == token:: Token :: Semi {
@@ -3208,7 +3244,19 @@ impl<'a> Parser<'a> {
3208
3244
try!( self . parse_inner_attributes ( ) ) . into_thin_attrs ( ) ) ;
3209
3245
let mut arms: Vec < Arm > = Vec :: new ( ) ;
3210
3246
while self . token != token:: CloseDelim ( token:: Brace ) {
3211
- arms. push ( try!( self . parse_arm ( ) ) ) ;
3247
+ match self . parse_arm ( ) {
3248
+ Ok ( arm) => arms. push ( arm) ,
3249
+ Err ( mut e) => {
3250
+ // Recover by skipping to the end of the block.
3251
+ e. emit ( ) ;
3252
+ self . recover_stmt ( ) ;
3253
+ let hi = self . span . hi ;
3254
+ if self . token == token:: CloseDelim ( token:: Brace ) {
3255
+ self . bump ( ) ;
3256
+ }
3257
+ return Ok ( self . mk_expr ( lo, hi, ExprMatch ( discriminant, arms) , attrs) ) ;
3258
+ }
3259
+ }
3212
3260
}
3213
3261
let hi = self . span . hi ;
3214
3262
self . bump ( ) ;
@@ -3566,7 +3614,11 @@ impl<'a> Parser<'a> {
3566
3614
}
3567
3615
// Parse struct pattern
3568
3616
self . bump ( ) ;
3569
- let ( fields, etc) = try!( self . parse_pat_fields ( ) ) ;
3617
+ let ( fields, etc) = self . parse_pat_fields ( ) . unwrap_or_else ( |mut e| {
3618
+ e. emit ( ) ;
3619
+ self . recover_stmt ( ) ;
3620
+ ( vec ! [ ] , false )
3621
+ } ) ;
3570
3622
self . bump ( ) ;
3571
3623
pat = PatKind :: Struct ( path, fields, etc) ;
3572
3624
}
@@ -3720,10 +3772,72 @@ impl<'a> Parser<'a> {
3720
3772
3721
3773
/// Parse a statement. may include decl.
3722
3774
pub fn parse_stmt ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3723
- Ok ( try!( self . parse_stmt_ ( ) ) )
3775
+ Ok ( self . parse_stmt_ ( ) . map ( P ) )
3776
+ }
3777
+
3778
+ // Eat tokens until we can be relatively sure we reached the end of the
3779
+ // statement. This is something of a best-effort heuristic.
3780
+ //
3781
+ // We terminate when we find an unmatched `}` (without consuming it).
3782
+ fn recover_stmt ( & mut self ) {
3783
+ self . recover_stmt_ ( SemiColonMode :: Ignore )
3784
+ }
3785
+ // If `break_on_semi` is `Break`, then we will stop consuming tokens after
3786
+ // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
3787
+ // approximate - it can mean we break too early due to macros, but that
3788
+ // shoud only lead to sub-optimal recovery, not inaccurate parsing).
3789
+ fn recover_stmt_ ( & mut self , break_on_semi : SemiColonMode ) {
3790
+ let mut brace_depth = 0 ;
3791
+ let mut bracket_depth = 0 ;
3792
+ loop {
3793
+ match self . token {
3794
+ token:: OpenDelim ( token:: DelimToken :: Brace ) => {
3795
+ brace_depth += 1 ;
3796
+ self . bump ( ) ;
3797
+ }
3798
+ token:: OpenDelim ( token:: DelimToken :: Bracket ) => {
3799
+ bracket_depth += 1 ;
3800
+ self . bump ( ) ;
3801
+ }
3802
+ token:: CloseDelim ( token:: DelimToken :: Brace ) => {
3803
+ if brace_depth == 0 {
3804
+ return ;
3805
+ }
3806
+ brace_depth -= 1 ;
3807
+ self . bump ( ) ;
3808
+ }
3809
+ token:: CloseDelim ( token:: DelimToken :: Bracket ) => {
3810
+ bracket_depth -= 1 ;
3811
+ if bracket_depth < 0 {
3812
+ bracket_depth = 0 ;
3813
+ }
3814
+ self . bump ( ) ;
3815
+ }
3816
+ token:: Eof => return ,
3817
+ token:: Semi => {
3818
+ self . bump ( ) ;
3819
+ if break_on_semi == SemiColonMode :: Break &&
3820
+ brace_depth == 0 &&
3821
+ bracket_depth == 0 {
3822
+ return ;
3823
+ }
3824
+ }
3825
+ _ => {
3826
+ self . bump ( )
3827
+ }
3828
+ }
3829
+ }
3724
3830
}
3725
3831
3726
- fn parse_stmt_ ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3832
+ fn parse_stmt_ ( & mut self ) -> Option < Stmt > {
3833
+ self . parse_stmt_without_recovery ( ) . unwrap_or_else ( |mut e| {
3834
+ e. emit ( ) ;
3835
+ self . recover_stmt_ ( SemiColonMode :: Break ) ;
3836
+ None
3837
+ } )
3838
+ }
3839
+
3840
+ fn parse_stmt_without_recovery ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3727
3841
maybe_whole ! ( Some deref self , NtStmt ) ;
3728
3842
3729
3843
let attrs = try!( self . parse_outer_attributes ( ) ) ;
@@ -3879,7 +3993,7 @@ impl<'a> Parser<'a> {
3879
3993
let lo = self . span . lo ;
3880
3994
try!( self . expect ( & token:: OpenDelim ( token:: Brace ) ) ) ;
3881
3995
Ok ( ( try!( self . parse_inner_attributes ( ) ) ,
3882
- try!( self . parse_block_tail ( lo, BlockCheckMode :: Default ) ) ) )
3996
+ try!( self . parse_block_tail ( lo, BlockCheckMode :: Default ) ) ) )
3883
3997
}
3884
3998
3885
3999
/// Parse the rest of a block expression or function body
@@ -3889,7 +4003,7 @@ impl<'a> Parser<'a> {
3889
4003
let mut expr = None ;
3890
4004
3891
4005
while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
3892
- let Spanned { node, span} = if let Some ( s) = try! ( self . parse_stmt_ ( ) ) {
4006
+ let Spanned { node, span} = if let Some ( s) = self . parse_stmt_ ( ) {
3893
4007
s
3894
4008
} else {
3895
4009
// Found only `;` or `}`.
@@ -3974,17 +4088,21 @@ impl<'a> Parser<'a> {
3974
4088
} ) )
3975
4089
}
3976
4090
3977
- fn handle_expression_like_statement (
3978
- & mut self ,
3979
- e : P < Expr > ,
3980
- span : Span ,
3981
- stmts : & mut Vec < Stmt > ,
3982
- last_block_expr : & mut Option < P < Expr > > ) -> PResult < ' a , ( ) > {
4091
+ fn handle_expression_like_statement ( & mut self ,
4092
+ e : P < Expr > ,
4093
+ span : Span ,
4094
+ stmts : & mut Vec < Stmt > ,
4095
+ last_block_expr : & mut Option < P < Expr > > )
4096
+ -> PResult < ' a , ( ) > {
3983
4097
// expression without semicolon
3984
4098
if classify:: expr_requires_semi_to_be_stmt ( & e) {
3985
4099
// Just check for errors and recover; do not eat semicolon yet.
3986
- try!( self . commit_stmt ( & [ ] ,
3987
- & [ token:: Semi , token:: CloseDelim ( token:: Brace ) ] ) ) ;
4100
+ if let Err ( mut e) =
4101
+ self . commit_stmt ( & [ ] , & [ token:: Semi , token:: CloseDelim ( token:: Brace ) ] )
4102
+ {
4103
+ e. emit ( ) ;
4104
+ self . recover_stmt ( ) ;
4105
+ }
3988
4106
}
3989
4107
3990
4108
match self . token {
@@ -4381,13 +4499,13 @@ impl<'a> Parser<'a> {
4381
4499
}
4382
4500
) ) ;
4383
4501
4502
+ let args: Vec < _ > = args. into_iter ( ) . filter_map ( |x| x) . collect ( ) ;
4503
+
4384
4504
if variadic && args. is_empty ( ) {
4385
4505
self . span_err ( sp,
4386
4506
"variadic function must be declared with at least one named argument" ) ;
4387
4507
}
4388
4508
4389
- let args = args. into_iter ( ) . filter_map ( |x| x) . collect ( ) ;
4390
-
4391
4509
Ok ( ( args, variadic) )
4392
4510
}
4393
4511
0 commit comments