@@ -1531,21 +1531,32 @@ fn parse_let(p: parser) -> @ast::decl {
1531
1531
ret @spanned ( lo, p. last_span . hi , ast:: decl_local ( locals) ) ;
1532
1532
}
1533
1533
1534
- fn parse_stmt ( p : parser ) -> @ast:: stmt {
1534
+ fn parse_stmt ( p : parser , first_item_attrs : [ ast:: attribute ] ) -> @ast:: stmt {
1535
+ fn check_expected_item ( p : parser , current_attrs : [ ast:: attribute ] ) {
1536
+ // If we have attributes then we should have an item
1537
+ if vec:: is_not_empty ( current_attrs) {
1538
+ p. fatal ( "expected item" ) ;
1539
+ }
1540
+ }
1541
+
1535
1542
let lo = p. span . lo ;
1536
- if eat_word ( p, "let" ) {
1543
+ if is_word ( p, "let" ) {
1544
+ check_expected_item ( p, first_item_attrs) ;
1545
+ expect_word ( p, "let" ) ;
1537
1546
let decl = parse_let ( p) ;
1538
1547
ret @spanned ( lo, decl. span . hi , ast:: stmt_decl ( decl, p. get_id ( ) ) ) ;
1539
1548
} else {
1540
1549
let item_attrs;
1541
- alt parse_outer_attrs_or_ext ( p) {
1550
+ alt parse_outer_attrs_or_ext ( p, first_item_attrs ) {
1542
1551
none. { item_attrs = [ ] ; }
1543
1552
some ( left ( attrs) ) { item_attrs = attrs; }
1544
1553
some ( right ( ext) ) {
1545
1554
ret @spanned ( lo, ext. span . hi , ast:: stmt_expr ( ext, p. get_id ( ) ) ) ;
1546
1555
}
1547
1556
}
1548
1557
1558
+ let item_attrs = first_item_attrs + item_attrs;
1559
+
1549
1560
alt parse_item( p, item_attrs) {
1550
1561
some ( i) {
1551
1562
let hi = i. span . hi ;
@@ -1555,10 +1566,7 @@ fn parse_stmt(p: parser) -> @ast::stmt {
1555
1566
none ( ) { /* fallthrough */ }
1556
1567
}
1557
1568
1558
- // If we have attributes then we should have an item
1559
- if vec:: len ( item_attrs) > 0 u {
1560
- ret p. fatal ( "expected item" ) ;
1561
- }
1569
+ check_expected_item ( p, item_attrs) ;
1562
1570
1563
1571
// Remainder are line-expr stmts.
1564
1572
let e = parse_expr_res ( p, RESTRICT_STMT_EXPR ) ;
@@ -1605,16 +1613,37 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
1605
1613
}
1606
1614
1607
1615
fn parse_block ( p : parser ) -> ast:: blk {
1616
+ let ( attrs, blk) = parse_inner_attrs_and_block ( p, false ) ;
1617
+ assert vec:: is_empty ( attrs) ;
1618
+ ret blk;
1619
+ }
1620
+
1621
+ fn parse_inner_attrs_and_block (
1622
+ p : parser , parse_attrs : bool ) -> ( [ ast:: attribute ] , ast:: blk ) {
1623
+
1624
+ fn maybe_parse_inner_attrs_and_next (
1625
+ p : parser , parse_attrs : bool ) ->
1626
+ { inner : [ ast:: attribute ] , next : [ ast:: attribute ] } {
1627
+ if parse_attrs {
1628
+ parse_inner_attrs_and_next ( p)
1629
+ } else {
1630
+ { inner: [ ] , next: [ ] }
1631
+ }
1632
+ }
1633
+
1608
1634
let lo = p. span . lo ;
1609
1635
if eat_word ( p, "unchecked" ) {
1610
1636
expect ( p, token:: LBRACE ) ;
1611
- be parse_block_tail ( p, lo, ast:: unchecked_blk) ;
1637
+ let { inner, next} = maybe_parse_inner_attrs_and_next ( p, parse_attrs) ;
1638
+ ret ( inner, parse_block_tail_ ( p, lo, ast:: unchecked_blk, next) ) ;
1612
1639
} else if eat_word ( p, "unsafe" ) {
1613
1640
expect ( p, token:: LBRACE ) ;
1614
- be parse_block_tail ( p, lo, ast:: unsafe_blk) ;
1641
+ let { inner, next} = maybe_parse_inner_attrs_and_next ( p, parse_attrs) ;
1642
+ ret ( inner, parse_block_tail_ ( p, lo, ast:: unsafe_blk, next) ) ;
1615
1643
} else {
1616
1644
expect ( p, token:: LBRACE ) ;
1617
- be parse_block_tail ( p, lo, ast:: default_blk) ;
1645
+ let { inner, next} = maybe_parse_inner_attrs_and_next ( p, parse_attrs) ;
1646
+ ret ( inner, parse_block_tail_ ( p, lo, ast:: default_blk, next) ) ;
1618
1647
}
1619
1648
}
1620
1649
@@ -1630,15 +1659,28 @@ fn parse_block_no_value(p: parser) -> ast::blk {
1630
1659
// necessary, and this should take a qualifier.
1631
1660
// some blocks start with "#{"...
1632
1661
fn parse_block_tail ( p : parser , lo : uint , s : ast:: blk_check_mode ) -> ast:: blk {
1633
- let stmts = [ ] , expr = none;
1634
- let view_items = parse_view_import_only ( p) ;
1662
+ parse_block_tail_ ( p, lo, s, [ ] )
1663
+ }
1664
+
1665
+ fn parse_block_tail_ ( p : parser , lo : uint , s : ast:: blk_check_mode ,
1666
+ first_item_attrs : [ ast:: attribute ] ) -> ast:: blk {
1667
+ let stmts = [ ] ;
1668
+ let expr = none;
1669
+ let view_items = maybe_parse_view_import_only ( p, first_item_attrs) ;
1670
+ let initial_attrs = first_item_attrs;
1671
+
1672
+ if p. token == token:: RBRACE && !vec:: is_empty ( initial_attrs) {
1673
+ p. fatal ( "expected item" ) ;
1674
+ }
1675
+
1635
1676
while p. token != token:: RBRACE {
1636
1677
alt p. token {
1637
1678
token:: SEMI . {
1638
1679
p . bump ( ) ; // empty
1639
1680
}
1640
1681
_ {
1641
- let stmt = parse_stmt ( p) ;
1682
+ let stmt = parse_stmt ( p, initial_attrs) ;
1683
+ initial_attrs = [ ] ;
1642
1684
alt stmt. node {
1643
1685
ast:: stmt_expr ( e, stmt_id) { // Expression without semicolon:
1644
1686
alt p. token {
@@ -1751,7 +1793,8 @@ fn parse_item_fn(p: parser, purity: ast::purity,
1751
1793
let lo = p. last_span . lo ;
1752
1794
let t = parse_fn_header ( p) ;
1753
1795
let decl = parse_fn_decl ( p, purity) ;
1754
- let body = parse_block ( p) ;
1796
+ let ( inner_attrs, body) = parse_inner_attrs_and_block ( p, true ) ;
1797
+ let attrs = attrs + inner_attrs;
1755
1798
ret mk_item( p, lo, body. span . hi , t. ident ,
1756
1799
ast:: item_fn ( decl, t. tps , body) , attrs) ;
1757
1800
}
@@ -1832,8 +1875,7 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
1832
1875
fn parse_mod_items ( p : parser , term : token:: token ,
1833
1876
first_item_attrs : [ ast:: attribute ] ) -> ast:: _mod {
1834
1877
// Shouldn't be any view items since we've already parsed an item attr
1835
- let view_items =
1836
- if vec:: len ( first_item_attrs) == 0 u { parse_view ( p) } else { [ ] } ;
1878
+ let view_items = maybe_parse_view ( p, first_item_attrs) ;
1837
1879
let items: [ @ast:: item ] = [ ] ;
1838
1880
let initial_attrs = first_item_attrs;
1839
1881
while p. token != term {
@@ -2134,14 +2176,20 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
2134
2176
// extensions, which both begin with token.POUND
2135
2177
type attr_or_ext = option:: t < either:: t < [ ast:: attribute ] , @ast:: expr > > ;
2136
2178
2137
- fn parse_outer_attrs_or_ext ( p : parser ) -> attr_or_ext {
2179
+ fn parse_outer_attrs_or_ext (
2180
+ p : parser ,
2181
+ first_item_attrs : [ ast:: attribute ] ) -> attr_or_ext {
2182
+ let expect_item_next = vec:: is_not_empty ( first_item_attrs) ;
2138
2183
if p. token == token:: POUND {
2139
2184
let lo = p. span . lo ;
2140
- p . bump ( ) ;
2141
- if p . token == token :: LBRACKET {
2185
+ if p . look_ahead ( 1 u ) == token :: LBRACKET {
2186
+ p . bump ( ) ;
2142
2187
let first_attr = parse_attribute_naked ( p, ast:: attr_outer, lo) ;
2143
2188
ret some( left ( [ first_attr] + parse_outer_attributes ( p) ) ) ;
2144
- } else if !( p. token == token:: LT || p. token == token:: LBRACKET ) {
2189
+ } else if !( p. look_ahead ( 1 u) == token:: LT
2190
+ || p. look_ahead ( 1 u) == token:: LBRACKET
2191
+ || expect_item_next) {
2192
+ p. bump ( ) ;
2145
2193
ret some( right ( parse_syntax_ext_naked ( p, lo) ) ) ;
2146
2194
} else { ret none; }
2147
2195
} else { ret none; }
@@ -2182,6 +2230,10 @@ fn parse_inner_attrs_and_next(p: parser) ->
2182
2230
let inner_attrs: [ ast:: attribute ] = [ ] ;
2183
2231
let next_outer_attrs: [ ast:: attribute ] = [ ] ;
2184
2232
while p. token == token:: POUND {
2233
+ if p. look_ahead ( 1 u) != token:: LBRACKET {
2234
+ // This is an extension
2235
+ break ;
2236
+ }
2185
2237
let attr = parse_attribute ( p, ast:: attr_inner) ;
2186
2238
if p. token == token:: SEMI {
2187
2239
p. bump ( ) ;
@@ -2377,22 +2429,37 @@ fn is_view_item(p: parser) -> bool {
2377
2429
}
2378
2430
}
2379
2431
2380
- fn parse_view ( p : parser ) -> [ @ast:: view_item ] {
2381
- parse_view_while ( p, is_view_item)
2432
+ fn maybe_parse_view (
2433
+ p : parser ,
2434
+ first_item_attrs : [ ast:: attribute ] ) -> [ @ast:: view_item ] {
2435
+
2436
+ maybe_parse_view_while ( p, first_item_attrs, is_view_item)
2382
2437
}
2383
2438
2384
- fn parse_view_import_only ( p : parser ) -> [ @ast:: view_item ] {
2385
- parse_view_while ( p, bind is_word ( _, "import" ) )
2439
+ fn maybe_parse_view_import_only (
2440
+ p : parser ,
2441
+ first_item_attrs : [ ast:: attribute ] ) -> [ @ast:: view_item ] {
2442
+
2443
+ maybe_parse_view_while ( p, first_item_attrs, bind is_word ( _, "import" ) )
2386
2444
}
2387
2445
2388
- fn parse_view_while ( p : parser , f : fn @( parser ) -> bool ) -> [ @ast:: view_item ] {
2389
- let items = [ ] ;
2390
- while f ( p) { items += [ parse_view_item ( p) ] ; }
2391
- ret items;
2446
+ fn maybe_parse_view_while (
2447
+ p : parser ,
2448
+ first_item_attrs : [ ast:: attribute ] ,
2449
+ f : fn @( parser ) -> bool ) -> [ @ast:: view_item ] {
2450
+
2451
+ if vec:: len ( first_item_attrs) == 0 u {
2452
+ let items = [ ] ;
2453
+ while f ( p) { items += [ parse_view_item ( p) ] ; }
2454
+ ret items;
2455
+ } else {
2456
+ // Shouldn't be any view items since we've already parsed an item attr
2457
+ ret [ ] ;
2458
+ }
2392
2459
}
2393
2460
2394
2461
fn parse_native_view ( p : parser ) -> [ @ast:: view_item ] {
2395
- parse_view_while ( p , is_view_item)
2462
+ maybe_parse_view_while ( p , [ ] , is_view_item)
2396
2463
}
2397
2464
2398
2465
fn parse_crate_from_source_file ( input : str , cfg : ast:: crate_cfg ,
0 commit comments