@@ -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,
@@ -591,20 +593,6 @@ impl<'a> Parser<'a> {
591
593
}
592
594
}
593
595
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
-
608
596
/// Check if the next token is `tok`, and return `true` if so.
609
597
///
610
598
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
@@ -1763,8 +1751,8 @@ impl<'a> Parser<'a> {
1763
1751
LifetimeAndTypesWithColons => {
1764
1752
self.parse_path_segments_with_colons()?
1765
1753
}
1766
- NoTypesAllowed => {
1767
- self.parse_path_segments_without_types()?
1754
+ NoTypesAllowed | ImportPrefix => {
1755
+ self.parse_path_segments_without_types(mode == ImportPrefix )?
1768
1756
}
1769
1757
};
1770
1758
path.segments.extend(segments);
@@ -1801,8 +1789,8 @@ impl<'a> Parser<'a> {
1801
1789
LifetimeAndTypesWithColons => {
1802
1790
self.parse_path_segments_with_colons()?
1803
1791
}
1804
- NoTypesAllowed => {
1805
- self.parse_path_segments_without_types()?
1792
+ NoTypesAllowed | ImportPrefix => {
1793
+ self.parse_path_segments_without_types(mode == ImportPrefix )?
1806
1794
}
1807
1795
};
1808
1796
@@ -1920,7 +1908,8 @@ impl<'a> Parser<'a> {
1920
1908
1921
1909
/// Examples:
1922
1910
/// - `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>> {
1924
1913
let mut segments = Vec::new();
1925
1914
loop {
1926
1915
// First, parse an identifier.
@@ -1932,9 +1921,11 @@ impl<'a> Parser<'a> {
1932
1921
parameters: ast::PathParameters::none()
1933
1922
});
1934
1923
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( ) {
1937
1926
return Ok(segments);
1927
+ } else {
1928
+ self.bump();
1938
1929
}
1939
1930
}
1940
1931
}
@@ -6127,106 +6118,67 @@ impl<'a> Parser<'a> {
6127
6118
self.parse_item_(attrs, true, false)
6128
6119
}
6129
6120
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
+ }
6130
6145
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
6136
6152
fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
6137
6153
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(),
6151
6159
span: mk_sp(lo, self.span.hi),
6152
- global: is_global,
6153
- segments: Vec::new()
6154
6160
};
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::*`
6163
6167
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)) {
6194
6169
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))))
6214
6174
}
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))))
6215
6180
}
6216
6181
}
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))))
6230
6182
}
6231
6183
6232
6184
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
0 commit comments