@@ -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 ,
@@ -589,20 +591,6 @@ impl<'a> Parser<'a> {
589591 }
590592 }
591593
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-
606594 /// Check if the next token is `tok`, and return `true` if so.
607595 ///
608596 /// This method will automatically add `tok` to `expected_tokens` if `tok` is not
@@ -1761,8 +1749,8 @@ impl<'a> Parser<'a> {
17611749 LifetimeAndTypesWithColons => {
17621750 self . parse_path_segments_with_colons ( ) ?
17631751 }
1764- NoTypesAllowed => {
1765- self . parse_path_segments_without_types ( ) ?
1752+ NoTypesAllowed | ImportPrefix => {
1753+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
17661754 }
17671755 } ;
17681756 path. segments . extend ( segments) ;
@@ -1799,8 +1787,8 @@ impl<'a> Parser<'a> {
17991787 LifetimeAndTypesWithColons => {
18001788 self . parse_path_segments_with_colons ( ) ?
18011789 }
1802- NoTypesAllowed => {
1803- self . parse_path_segments_without_types ( ) ?
1790+ NoTypesAllowed | ImportPrefix => {
1791+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
18041792 }
18051793 } ;
18061794
@@ -1918,7 +1906,8 @@ impl<'a> Parser<'a> {
19181906
19191907 /// Examples:
19201908 /// - `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 > > {
19221911 let mut segments = Vec :: new ( ) ;
19231912 loop {
19241913 // First, parse an identifier.
@@ -1930,9 +1919,11 @@ impl<'a> Parser<'a> {
19301919 parameters : ast:: PathParameters :: none ( )
19311920 } ) ;
19321921
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 ( ) {
19351924 return Ok ( segments) ;
1925+ } else {
1926+ self . bump ( ) ;
19361927 }
19371928 }
19381929 }
@@ -6119,106 +6110,67 @@ impl<'a> Parser<'a> {
61196110 self . parse_item_ ( attrs, true , false )
61206111 }
61216112
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+ }
61226137
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
61286144 fn parse_view_path ( & mut self ) -> PResult < ' a , P < ViewPath > > {
61296145 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 ( ) ,
61436151 span : mk_sp ( lo, self . span . hi ) ,
6144- global : is_global,
6145- segments : Vec :: new ( )
61466152 } ;
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::*`
61556159 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 ) ) {
61866161 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) ) ) )
62066166 }
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) ) ) )
62076172 }
62086173 }
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) ) ) )
62226174 }
62236175
62246176 fn parse_rename ( & mut self ) -> PResult < ' a , Option < Ident > > {
0 commit comments