@@ -2588,20 +2588,22 @@ pub impl Parser {
2588
2588
} )
2589
2589
}
2590
2590
2591
- // parse a statement. may include decl
2592
- fn parse_stmt ( & self , first_item_attrs : ~[ attribute ] ) -> @stmt {
2591
+ // parse a statement. may include decl.
2592
+ // precondition: any attributes are parsed already
2593
+ fn parse_stmt ( & self , item_attrs : ~[ attribute ] ) -> @stmt {
2593
2594
maybe_whole ! ( self , nt_stmt) ;
2594
2595
2595
2596
fn check_expected_item ( p : & Parser , current_attrs : & [ attribute ] ) {
2596
2597
// If we have attributes then we should have an item
2597
2598
if !current_attrs. is_empty ( ) {
2598
- p. fatal ( ~"expected item after attrs") ;
2599
+ p. span_err ( * p. last_span ,
2600
+ ~"expected item after attributes") ;
2599
2601
}
2600
2602
}
2601
2603
2602
2604
let lo = self . span . lo ;
2603
2605
if self . is_keyword ( "let" ) {
2604
- check_expected_item ( self , first_item_attrs ) ;
2606
+ check_expected_item ( self , item_attrs ) ;
2605
2607
self . expect_keyword ( "let" ) ;
2606
2608
let decl = self . parse_let ( ) ;
2607
2609
return @spanned ( lo, decl. span . hi , stmt_decl ( decl, self . get_id ( ) ) ) ;
@@ -2614,7 +2616,7 @@ pub impl Parser {
2614
2616
// to the macro clause of parse_item_or_view_item. This
2615
2617
// could use some cleanup, it appears to me.
2616
2618
2617
- check_expected_item ( self , first_item_attrs ) ;
2619
+ check_expected_item ( self , item_attrs ) ;
2618
2620
2619
2621
// Potential trouble: if we allow macros with paths instead of
2620
2622
// idents, we'd need to look ahead past the whole path here...
@@ -2650,9 +2652,6 @@ pub impl Parser {
2650
2652
}
2651
2653
2652
2654
} else {
2653
- let item_attrs = vec:: append ( first_item_attrs,
2654
- self . parse_outer_attributes ( ) ) ;
2655
-
2656
2655
match self . parse_item_or_view_item ( /*bad*/ copy item_attrs,
2657
2656
false ) {
2658
2657
iovi_item( i) => {
@@ -2727,6 +2726,7 @@ pub impl Parser {
2727
2726
let mut stmts = ~[ ] ;
2728
2727
let mut expr = None ;
2729
2728
2729
+ // wouldn't it be more uniform to parse view items only, here?
2730
2730
let ParsedItemsAndViewItems {
2731
2731
attrs_remaining : attrs_remaining,
2732
2732
view_items : view_items,
@@ -2741,23 +2741,29 @@ pub impl Parser {
2741
2741
stmt_decl ( decl, self . get_id ( ) ) ) ) ;
2742
2742
}
2743
2743
2744
- let mut initial_attrs = attrs_remaining;
2745
-
2746
- if * self . token == token:: RBRACE && !vec:: is_empty ( initial_attrs) {
2747
- self . fatal ( ~"expected item") ;
2748
- }
2744
+ let mut attributes_box = attrs_remaining;
2749
2745
2750
- while * self . token != token:: RBRACE {
2746
+ while ( * self . token != token:: RBRACE ) {
2747
+ // parsing items even when they're not allowed lets us give
2748
+ // better error messages and recover more gracefully.
2749
+ attributes_box. push_all ( self . parse_outer_attributes ( ) ) ;
2751
2750
match * self . token {
2752
2751
token:: SEMI => {
2752
+ if !vec:: is_empty ( attributes_box) {
2753
+ self . span_err ( * self . last_span , ~"expected item after attributes") ;
2754
+ attributes_box = ~[ ] ;
2755
+ }
2753
2756
self . bump ( ) ; // empty
2754
2757
}
2758
+ token:: RBRACE => {
2759
+ // fall through and out.
2760
+ }
2755
2761
_ => {
2756
- let stmt = self . parse_stmt ( initial_attrs ) ;
2757
- initial_attrs = ~[ ] ;
2762
+ let stmt = self . parse_stmt ( attributes_box ) ;
2763
+ attributes_box = ~[ ] ;
2758
2764
match stmt. node {
2759
2765
stmt_expr( e, stmt_id) => {
2760
- // Expression without semicolon
2766
+ // expression without semicolon
2761
2767
match * self . token {
2762
2768
token:: SEMI => {
2763
2769
self . bump ( ) ;
@@ -2773,7 +2779,7 @@ pub impl Parser {
2773
2779
self . fatal (
2774
2780
fmt ! (
2775
2781
"expected `;` or `}` after \
2776
- expression but found `%s`",
2782
+ expression but found `%s`",
2777
2783
self . token_to_str( & t)
2778
2784
)
2779
2785
) ;
@@ -2782,9 +2788,8 @@ pub impl Parser {
2782
2788
}
2783
2789
}
2784
2790
}
2785
-
2786
2791
stmt_mac( ref m, _) => {
2787
- // Statement macro; might be an expr
2792
+ // statement macro; might be an expr
2788
2793
match * self . token {
2789
2794
token:: SEMI => {
2790
2795
self . bump ( ) ;
@@ -2803,8 +2808,7 @@ pub impl Parser {
2803
2808
_ => { stmts. push ( stmt) ; }
2804
2809
}
2805
2810
}
2806
-
2807
- _ => { // All other kinds of statements:
2811
+ _ => { // all other kinds of statements:
2808
2812
stmts. push ( stmt) ;
2809
2813
2810
2814
if classify:: stmt_ends_with_semi ( stmt) {
@@ -2815,6 +2819,11 @@ pub impl Parser {
2815
2819
}
2816
2820
}
2817
2821
}
2822
+
2823
+ if !vec:: is_empty ( attributes_box) {
2824
+ self . span_err ( * self . last_span , ~"expected item after attributes") ;
2825
+ }
2826
+
2818
2827
let hi = self . span . hi ;
2819
2828
self . bump ( ) ;
2820
2829
let bloc = ast:: blk_ {
@@ -3519,7 +3528,7 @@ pub impl Parser {
3519
3528
3520
3529
if first && attrs_remaining_len > 0 u {
3521
3530
// We parsed attributes for the first item but didn't find it
3522
- self. fatal ( ~"expected item") ;
3531
+ self. span_err ( * self . last_span , ~"expected item after attributes ") ;
3523
3532
}
3524
3533
3525
3534
ast:: _mod { view_items: view_items, items: items }
@@ -3724,11 +3733,15 @@ pub impl Parser {
3724
3733
first_item_attrs: ~[ attribute] )
3725
3734
-> foreign_mod {
3726
3735
let ParsedItemsAndViewItems {
3727
- attrs_remaining : _ ,
3736
+ attrs_remaining : attrs_remaining ,
3728
3737
view_items : view_items,
3729
3738
items : _,
3730
3739
foreign_items : foreign_items
3731
3740
} = self . parse_foreign_items( first_item_attrs, true ) ;
3741
+ if ( ! attrs_remaining. is_empty( ) ) {
3742
+ self . span_err( * self . last_span,
3743
+ ~"expected item after attributes") ;
3744
+ }
3732
3745
assert ! ( * self . token == token:: RBRACE ) ;
3733
3746
ast:: foreign_mod {
3734
3747
sort : sort,
0 commit comments