@@ -81,6 +81,8 @@ type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
8181pub enum PathParsingMode {
8282 /// A path with no type parameters; e.g. `foo::bar::Baz`
8383 NoTypesAllowed ,
84+ /// Same as `NoTypesAllowed`, but may end with `::{` or `::*`, which are left unparsed
85+ ImportPrefix ,
8486 /// A path with a lifetime and type parameters, with no double colons
8587 /// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
8688 LifetimeAndTypesWithoutColons ,
@@ -591,20 +593,6 @@ impl<'a> Parser<'a> {
591593 }
592594 }
593595
594- pub fn parse_path_list_item ( & mut self ) -> PResult < ' a , ast:: PathListItem > {
595- let lo = self . span . lo ;
596- let node = if self . eat_keyword ( keywords:: SelfValue ) {
597- let rename = self . parse_rename ( ) ?;
598- ast:: PathListItemKind :: Mod { id : ast:: DUMMY_NODE_ID , rename : rename }
599- } else {
600- let ident = self . parse_ident ( ) ?;
601- let rename = self . parse_rename ( ) ?;
602- ast:: PathListItemKind :: Ident { name : ident, rename : rename, id : ast:: DUMMY_NODE_ID }
603- } ;
604- let hi = self . last_span . hi ;
605- Ok ( spanned ( lo, hi, node) )
606- }
607-
608596 /// Check if the next token is `tok`, and return `true` if so.
609597 ///
610598 /// This method will automatically add `tok` to `expected_tokens` if `tok` is not
@@ -1763,8 +1751,8 @@ impl<'a> Parser<'a> {
17631751 LifetimeAndTypesWithColons => {
17641752 self . parse_path_segments_with_colons ( ) ?
17651753 }
1766- NoTypesAllowed => {
1767- self . parse_path_segments_without_types ( ) ?
1754+ NoTypesAllowed | ImportPrefix => {
1755+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
17681756 }
17691757 } ;
17701758 path. segments . extend ( segments) ;
@@ -1801,8 +1789,8 @@ impl<'a> Parser<'a> {
18011789 LifetimeAndTypesWithColons => {
18021790 self . parse_path_segments_with_colons ( ) ?
18031791 }
1804- NoTypesAllowed => {
1805- self . parse_path_segments_without_types ( ) ?
1792+ NoTypesAllowed | ImportPrefix => {
1793+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
18061794 }
18071795 } ;
18081796
@@ -1920,7 +1908,8 @@ impl<'a> Parser<'a> {
19201908
19211909 /// Examples:
19221910 /// - `a::b::c`
1923- pub fn parse_path_segments_without_types ( & mut self ) -> PResult < ' a , Vec < ast:: PathSegment > > {
1911+ pub fn parse_path_segments_without_types ( & mut self , import_prefix : bool )
1912+ -> PResult < ' a , Vec < ast:: PathSegment > > {
19241913 let mut segments = Vec :: new ( ) ;
19251914 loop {
19261915 // First, parse an identifier.
@@ -1932,9 +1921,11 @@ impl<'a> Parser<'a> {
19321921 parameters : ast:: PathParameters :: none ( )
19331922 } ) ;
19341923
1935- // If we do not see a `::`, stop.
1936- if !self . eat ( & token:: ModSep ) {
1924+ // If we do not see a `::` or see `::{`/`::*` , stop.
1925+ if !self . check ( & token:: ModSep ) || import_prefix && self . is_import_coupler ( ) {
19371926 return Ok ( segments) ;
1927+ } else {
1928+ self . bump ( ) ;
19381929 }
19391930 }
19401931 }
@@ -6127,106 +6118,67 @@ impl<'a> Parser<'a> {
61276118 self . parse_item_ ( attrs, true , false )
61286119 }
61296120
6121+ fn parse_path_list_items ( & mut self ) -> PResult < ' a , Vec < ast:: PathListItem > > {
6122+ self . parse_unspanned_seq ( & token:: OpenDelim ( token:: Brace ) ,
6123+ & token:: CloseDelim ( token:: Brace ) ,
6124+ SeqSep :: trailing_allowed ( token:: Comma ) , |this| {
6125+ let lo = this. span . lo ;
6126+ let node = if this. eat_keyword ( keywords:: SelfValue ) {
6127+ let rename = this. parse_rename ( ) ?;
6128+ ast:: PathListItemKind :: Mod { id : ast:: DUMMY_NODE_ID , rename : rename }
6129+ } else {
6130+ let ident = this. parse_ident ( ) ?;
6131+ let rename = this. parse_rename ( ) ?;
6132+ ast:: PathListItemKind :: Ident { name : ident, rename : rename, id : ast:: DUMMY_NODE_ID }
6133+ } ;
6134+ let hi = this. last_span . hi ;
6135+ Ok ( spanned ( lo, hi, node) )
6136+ } )
6137+ }
6138+
6139+ /// `::{` or `::*`
6140+ fn is_import_coupler ( & mut self ) -> bool {
6141+ self . check ( & token:: ModSep ) &&
6142+ self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Brace ) ||
6143+ * t == token:: BinOp ( token:: Star ) )
6144+ }
61306145
6131- /// Matches view_path : MOD? non_global_path as IDENT
6132- /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
6133- /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
6134- /// | MOD? non_global_path MOD_SEP STAR
6135- /// | MOD? non_global_path
6146+ /// Matches ViewPath:
6147+ /// MOD_SEP? non_global_path
6148+ /// MOD_SEP? non_global_path as IDENT
6149+ /// MOD_SEP? non_global_path MOD_SEP STAR
6150+ /// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE
6151+ /// MOD_SEP? LBRACE item_seq RBRACE
61366152 fn parse_view_path ( & mut self ) -> PResult < ' a , P < ViewPath > > {
61376153 let lo = self . span . lo ;
6138-
6139- // Allow a leading :: because the paths are absolute either way.
6140- // This occurs with "use $crate::..." in macros.
6141- let is_global = self . eat ( & token:: ModSep ) ;
6142-
6143- if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
6144- // use {foo,bar}
6145- let idents = self . parse_unspanned_seq (
6146- & token:: OpenDelim ( token:: Brace ) ,
6147- & token:: CloseDelim ( token:: Brace ) ,
6148- SeqSep :: trailing_allowed ( token:: Comma ) ,
6149- |p| p. parse_path_list_item ( ) ) ?;
6150- let path = ast:: Path {
6154+ if self . check ( & token:: OpenDelim ( token:: Brace ) ) || self . is_import_coupler ( ) {
6155+ // `{foo, bar}` or `::{foo, bar}`
6156+ let prefix = ast:: Path {
6157+ global : self . eat ( & token:: ModSep ) ,
6158+ segments : Vec :: new ( ) ,
61516159 span : mk_sp ( lo, self . span . hi ) ,
6152- global : is_global,
6153- segments : Vec :: new ( )
61546160 } ;
6155- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( path, idents) ) ) ) ;
6156- }
6157-
6158- let first_ident = self . parse_ident ( ) ?;
6159- let mut path = vec ! ( first_ident) ;
6160- if let token:: ModSep = self . token {
6161- // foo::bar or foo::{a,b,c} or foo::*
6162- while self . check ( & token:: ModSep ) {
6161+ let items = self . parse_path_list_items ( ) ?;
6162+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( prefix, items) ) ) )
6163+ } else {
6164+ let prefix = self . parse_path ( ImportPrefix ) ?;
6165+ if self . is_import_coupler ( ) {
6166+ // `foo::bar::{a, b}` or `foo::bar::*`
61636167 self . bump ( ) ;
6164-
6165- match self . token {
6166- token:: Ident ( ..) => {
6167- let ident = self . parse_ident ( ) ?;
6168- path. push ( ident) ;
6169- }
6170-
6171- // foo::bar::{a,b,c}
6172- token:: OpenDelim ( token:: Brace ) => {
6173- let idents = self . parse_unspanned_seq (
6174- & token:: OpenDelim ( token:: Brace ) ,
6175- & token:: CloseDelim ( token:: Brace ) ,
6176- SeqSep :: trailing_allowed ( token:: Comma ) ,
6177- |p| p. parse_path_list_item ( )
6178- ) ?;
6179- let path = ast:: Path {
6180- span : mk_sp ( lo, self . span . hi ) ,
6181- global : is_global,
6182- segments : path. into_iter ( ) . map ( |identifier| {
6183- ast:: PathSegment {
6184- identifier : identifier,
6185- parameters : ast:: PathParameters :: none ( ) ,
6186- }
6187- } ) . collect ( )
6188- } ;
6189- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( path, idents) ) ) ) ;
6190- }
6191-
6192- // foo::bar::*
6193- token:: BinOp ( token:: Star ) => {
6168+ if self . check ( & token:: BinOp ( token:: Star ) ) {
61946169 self . bump ( ) ;
6195- let path = ast:: Path {
6196- span : mk_sp ( lo, self . span . hi ) ,
6197- global : is_global,
6198- segments : path. into_iter ( ) . map ( |identifier| {
6199- ast:: PathSegment {
6200- identifier : identifier,
6201- parameters : ast:: PathParameters :: none ( ) ,
6202- }
6203- } ) . collect ( )
6204- } ;
6205- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathGlob ( path) ) ) ) ;
6206- }
6207-
6208- // fall-through for case foo::bar::;
6209- token:: Semi => {
6210- self . span_err ( self . span , "expected identifier or `{` or `*`, found `;`" ) ;
6211- }
6212-
6213- _ => break
6170+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathGlob ( prefix) ) ) )
6171+ } else {
6172+ let items = self . parse_path_list_items ( ) ?;
6173+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( prefix, items) ) ) )
62146174 }
6175+ } else {
6176+ // `foo::bar` or `foo::bar as baz`
6177+ let rename = self . parse_rename ( ) ?.
6178+ unwrap_or ( prefix. segments . last ( ) . unwrap ( ) . identifier ) ;
6179+ Ok ( P ( spanned ( lo, self . last_span . hi , ViewPathSimple ( rename, prefix) ) ) )
62156180 }
62166181 }
6217- let mut rename_to = path[ path. len ( ) - 1 ] ;
6218- let path = ast:: Path {
6219- span : mk_sp ( lo, self . last_span . hi ) ,
6220- global : is_global,
6221- segments : path. into_iter ( ) . map ( |identifier| {
6222- ast:: PathSegment {
6223- identifier : identifier,
6224- parameters : ast:: PathParameters :: none ( ) ,
6225- }
6226- } ) . collect ( )
6227- } ;
6228- rename_to = self . parse_rename ( ) ?. unwrap_or ( rename_to) ;
6229- Ok ( P ( spanned ( lo, self . last_span . hi , ViewPathSimple ( rename_to, path) ) ) )
62306182 }
62316183
62326184 fn parse_rename ( & mut self ) -> PResult < ' a , Option < Ident > > {
0 commit comments