@@ -81,6 +81,8 @@ type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
81
81
pub enum PathParsingMode {
82
82
/// A path with no type parameters; e.g. `foo::bar::Baz`
83
83
NoTypesAllowed ,
84
+ /// Same as `NoTypesAllowed`, but may end with `::{` or `::*`, which are left unparsed
85
+ ImportPrefix ,
84
86
/// A path with a lifetime and type parameters, with no double colons
85
87
/// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
86
88
LifetimeAndTypesWithoutColons ,
@@ -589,20 +591,6 @@ impl<'a> Parser<'a> {
589
591
}
590
592
}
591
593
592
- pub fn parse_path_list_item ( & mut self ) -> PResult < ' a , ast:: PathListItem > {
593
- let lo = self . span . lo ;
594
- let node = if self . eat_keyword ( keywords:: SelfValue ) {
595
- let rename = self . parse_rename ( ) ?;
596
- ast:: PathListItemKind :: Mod { id : ast:: DUMMY_NODE_ID , rename : rename }
597
- } else {
598
- let ident = self . parse_ident ( ) ?;
599
- let rename = self . parse_rename ( ) ?;
600
- ast:: PathListItemKind :: Ident { name : ident, rename : rename, id : ast:: DUMMY_NODE_ID }
601
- } ;
602
- let hi = self . last_span . hi ;
603
- Ok ( spanned ( lo, hi, node) )
604
- }
605
-
606
594
/// Check if the next token is `tok`, and return `true` if so.
607
595
///
608
596
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
@@ -1761,8 +1749,8 @@ impl<'a> Parser<'a> {
1761
1749
LifetimeAndTypesWithColons => {
1762
1750
self . parse_path_segments_with_colons ( ) ?
1763
1751
}
1764
- NoTypesAllowed => {
1765
- self . parse_path_segments_without_types ( ) ?
1752
+ NoTypesAllowed | ImportPrefix => {
1753
+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
1766
1754
}
1767
1755
} ;
1768
1756
path. segments . extend ( segments) ;
@@ -1799,8 +1787,8 @@ impl<'a> Parser<'a> {
1799
1787
LifetimeAndTypesWithColons => {
1800
1788
self . parse_path_segments_with_colons ( ) ?
1801
1789
}
1802
- NoTypesAllowed => {
1803
- self . parse_path_segments_without_types ( ) ?
1790
+ NoTypesAllowed | ImportPrefix => {
1791
+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
1804
1792
}
1805
1793
} ;
1806
1794
@@ -1918,7 +1906,8 @@ impl<'a> Parser<'a> {
1918
1906
1919
1907
/// Examples:
1920
1908
/// - `a::b::c`
1921
- pub fn parse_path_segments_without_types ( & mut self ) -> PResult < ' a , Vec < ast:: PathSegment > > {
1909
+ pub fn parse_path_segments_without_types ( & mut self , import_prefix : bool )
1910
+ -> PResult < ' a , Vec < ast:: PathSegment > > {
1922
1911
let mut segments = Vec :: new ( ) ;
1923
1912
loop {
1924
1913
// First, parse an identifier.
@@ -1930,9 +1919,11 @@ impl<'a> Parser<'a> {
1930
1919
parameters : ast:: PathParameters :: none ( )
1931
1920
} ) ;
1932
1921
1933
- // If we do not see a `::`, stop.
1934
- if !self . eat ( & token:: ModSep ) {
1922
+ // If we do not see a `::` or see `::{`/`::*` , stop.
1923
+ if !self . check ( & token:: ModSep ) || import_prefix && self . is_import_coupler ( ) {
1935
1924
return Ok ( segments) ;
1925
+ } else {
1926
+ self . bump ( ) ;
1936
1927
}
1937
1928
}
1938
1929
}
@@ -6119,106 +6110,67 @@ impl<'a> Parser<'a> {
6119
6110
self . parse_item_ ( attrs, true , false )
6120
6111
}
6121
6112
6113
+ fn parse_path_list_items ( & mut self ) -> PResult < ' a , Vec < ast:: PathListItem > > {
6114
+ self . parse_unspanned_seq ( & token:: OpenDelim ( token:: Brace ) ,
6115
+ & token:: CloseDelim ( token:: Brace ) ,
6116
+ SeqSep :: trailing_allowed ( token:: Comma ) , |this| {
6117
+ let lo = this. span . lo ;
6118
+ let node = if this. eat_keyword ( keywords:: SelfValue ) {
6119
+ let rename = this. parse_rename ( ) ?;
6120
+ ast:: PathListItemKind :: Mod { id : ast:: DUMMY_NODE_ID , rename : rename }
6121
+ } else {
6122
+ let ident = this. parse_ident ( ) ?;
6123
+ let rename = this. parse_rename ( ) ?;
6124
+ ast:: PathListItemKind :: Ident { name : ident, rename : rename, id : ast:: DUMMY_NODE_ID }
6125
+ } ;
6126
+ let hi = this. last_span . hi ;
6127
+ Ok ( spanned ( lo, hi, node) )
6128
+ } )
6129
+ }
6130
+
6131
+ /// `::{` or `::*`
6132
+ fn is_import_coupler ( & mut self ) -> bool {
6133
+ self . check ( & token:: ModSep ) &&
6134
+ self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Brace ) ||
6135
+ * t == token:: BinOp ( token:: Star ) )
6136
+ }
6122
6137
6123
- /// Matches view_path : MOD? non_global_path as IDENT
6124
- /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
6125
- /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
6126
- /// | MOD? non_global_path MOD_SEP STAR
6127
- /// | MOD? non_global_path
6138
+ /// Matches ViewPath:
6139
+ /// MOD_SEP? non_global_path
6140
+ /// MOD_SEP? non_global_path as IDENT
6141
+ /// MOD_SEP? non_global_path MOD_SEP STAR
6142
+ /// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE
6143
+ /// MOD_SEP? LBRACE item_seq RBRACE
6128
6144
fn parse_view_path ( & mut self ) -> PResult < ' a , P < ViewPath > > {
6129
6145
let lo = self . span . lo ;
6130
-
6131
- // Allow a leading :: because the paths are absolute either way.
6132
- // This occurs with "use $crate::..." in macros.
6133
- let is_global = self . eat ( & token:: ModSep ) ;
6134
-
6135
- if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
6136
- // use {foo,bar}
6137
- let idents = self . parse_unspanned_seq (
6138
- & token:: OpenDelim ( token:: Brace ) ,
6139
- & token:: CloseDelim ( token:: Brace ) ,
6140
- SeqSep :: trailing_allowed ( token:: Comma ) ,
6141
- |p| p. parse_path_list_item ( ) ) ?;
6142
- let path = ast:: Path {
6146
+ if self . check ( & token:: OpenDelim ( token:: Brace ) ) || self . is_import_coupler ( ) {
6147
+ // `{foo, bar}` or `::{foo, bar}`
6148
+ let prefix = ast:: Path {
6149
+ global : self . eat ( & token:: ModSep ) ,
6150
+ segments : Vec :: new ( ) ,
6143
6151
span : mk_sp ( lo, self . span . hi ) ,
6144
- global : is_global,
6145
- segments : Vec :: new ( )
6146
6152
} ;
6147
- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( path, idents) ) ) ) ;
6148
- }
6149
-
6150
- let first_ident = self . parse_ident ( ) ?;
6151
- let mut path = vec ! ( first_ident) ;
6152
- if let token:: ModSep = self . token {
6153
- // foo::bar or foo::{a,b,c} or foo::*
6154
- while self . check ( & token:: ModSep ) {
6153
+ let items = self . parse_path_list_items ( ) ?;
6154
+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( prefix, items) ) ) )
6155
+ } else {
6156
+ let prefix = self . parse_path ( ImportPrefix ) ?;
6157
+ if self . is_import_coupler ( ) {
6158
+ // `foo::bar::{a, b}` or `foo::bar::*`
6155
6159
self . bump ( ) ;
6156
-
6157
- match self . token {
6158
- token:: Ident ( ..) => {
6159
- let ident = self . parse_ident ( ) ?;
6160
- path. push ( ident) ;
6161
- }
6162
-
6163
- // foo::bar::{a,b,c}
6164
- token:: OpenDelim ( token:: Brace ) => {
6165
- let idents = self . parse_unspanned_seq (
6166
- & token:: OpenDelim ( token:: Brace ) ,
6167
- & token:: CloseDelim ( token:: Brace ) ,
6168
- SeqSep :: trailing_allowed ( token:: Comma ) ,
6169
- |p| p. parse_path_list_item ( )
6170
- ) ?;
6171
- let path = ast:: Path {
6172
- span : mk_sp ( lo, self . span . hi ) ,
6173
- global : is_global,
6174
- segments : path. into_iter ( ) . map ( |identifier| {
6175
- ast:: PathSegment {
6176
- identifier : identifier,
6177
- parameters : ast:: PathParameters :: none ( ) ,
6178
- }
6179
- } ) . collect ( )
6180
- } ;
6181
- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( path, idents) ) ) ) ;
6182
- }
6183
-
6184
- // foo::bar::*
6185
- token:: BinOp ( token:: Star ) => {
6160
+ if self . check ( & token:: BinOp ( token:: Star ) ) {
6186
6161
self . bump ( ) ;
6187
- let path = ast:: Path {
6188
- span : mk_sp ( lo, self . span . hi ) ,
6189
- global : is_global,
6190
- segments : path. into_iter ( ) . map ( |identifier| {
6191
- ast:: PathSegment {
6192
- identifier : identifier,
6193
- parameters : ast:: PathParameters :: none ( ) ,
6194
- }
6195
- } ) . collect ( )
6196
- } ;
6197
- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathGlob ( path) ) ) ) ;
6198
- }
6199
-
6200
- // fall-through for case foo::bar::;
6201
- token:: Semi => {
6202
- self . span_err ( self . span , "expected identifier or `{` or `*`, found `;`" ) ;
6203
- }
6204
-
6205
- _ => break
6162
+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathGlob ( prefix) ) ) )
6163
+ } else {
6164
+ let items = self . parse_path_list_items ( ) ?;
6165
+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( prefix, items) ) ) )
6206
6166
}
6167
+ } else {
6168
+ // `foo::bar` or `foo::bar as baz`
6169
+ let rename = self . parse_rename ( ) ?.
6170
+ unwrap_or ( prefix. segments . last ( ) . unwrap ( ) . identifier ) ;
6171
+ Ok ( P ( spanned ( lo, self . last_span . hi , ViewPathSimple ( rename, prefix) ) ) )
6207
6172
}
6208
6173
}
6209
- let mut rename_to = path[ path. len ( ) - 1 ] ;
6210
- let path = ast:: Path {
6211
- span : mk_sp ( lo, self . last_span . hi ) ,
6212
- global : is_global,
6213
- segments : path. into_iter ( ) . map ( |identifier| {
6214
- ast:: PathSegment {
6215
- identifier : identifier,
6216
- parameters : ast:: PathParameters :: none ( ) ,
6217
- }
6218
- } ) . collect ( )
6219
- } ;
6220
- rename_to = self . parse_rename ( ) ?. unwrap_or ( rename_to) ;
6221
- Ok ( P ( spanned ( lo, self . last_span . hi , ViewPathSimple ( rename_to, path) ) ) )
6222
6174
}
6223
6175
6224
6176
fn parse_rename ( & mut self ) -> PResult < ' a , Option < Ident > > {
0 commit comments