diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2020-02-16 16:47:24 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2020-02-17 22:12:39 +0300 |
| commit | d33b3562e5e888eaffd2f8f1af08ca2afdbe542c (patch) | |
| tree | c92a51b70f308f083c031111df7074227cd5a521 /src/librustc_parse/parser | |
| parent | 0176a9eef845e7421b7e2f7ef015333a41a7c027 (diff) | |
| download | rust-d33b3562e5e888eaffd2f8f1af08ca2afdbe542c.tar.gz rust-d33b3562e5e888eaffd2f8f1af08ca2afdbe542c.zip | |
parser: Do not call `bump` recursively
Token normalization is merged directly into `bump`. Special "unknown macro variable" diagnostic for unexpected `$`s is removed as preventing legal code from compiling.
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/mod.rs | 75 |
1 files changed, 32 insertions, 43 deletions
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 79944dc35e5..4f96d33b83f 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -404,7 +404,8 @@ impl<'a> Parser<'a> { subparser_name, }; - parser.token = parser.next_tok(); + // Make parser point to the first token. + parser.bump(); if let Some(directory) = directory { parser.directory = directory; @@ -418,7 +419,6 @@ impl<'a> Parser<'a> { } } - parser.process_potential_macro_variable(); parser } @@ -430,7 +430,7 @@ impl<'a> Parser<'a> { self.unnormalized_prev_token.as_ref().unwrap_or(&self.prev_token) } - fn next_tok(&mut self) -> Token { + fn next_tok(&mut self, fallback_span: Span) -> Token { let mut next = if self.desugar_doc_comments { self.token_cursor.next_desugared() } else { @@ -438,7 +438,7 @@ impl<'a> Parser<'a> { }; if next.span.is_dummy() { // Tweak the location for better diagnostics, but keep syntactic context intact. - next.span = self.unnormalized_token().span.with_ctxt(next.span.ctxt()); + next.span = fallback_span.with_ctxt(next.span.ctxt()); } next } @@ -896,6 +896,24 @@ impl<'a> Parser<'a> { self.parse_delim_comma_seq(token::Paren, f) } + // Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`) + // tokens are replaced with usual identifier and lifetime tokens, + // so the former are never encountered during normal parsing. + fn normalize_token(token: &Token) -> Option<Token> { + match &token.kind { + token::Interpolated(nt) => match **nt { + token::NtIdent(ident, is_raw) => { + Some(Token::new(token::Ident(ident.name, is_raw), ident.span)) + } + token::NtLifetime(ident) => { + Some(Token::new(token::Lifetime(ident.name), ident.span)) + } + _ => None, + }, + _ => None, + } + } + /// Advance the parser by one token. pub fn bump(&mut self) { if self.prev_token.kind == TokenKind::Eof { @@ -905,16 +923,17 @@ impl<'a> Parser<'a> { } // Update the current and previous tokens. - let next_token = self.next_tok(); - self.prev_token = mem::replace(&mut self.token, next_token); + self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); + self.token = self.next_tok(self.unnormalized_prev_token().span); + if let Some(normalized_token) = Self::normalize_token(&self.token) { + self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); + } // Update fields derived from the previous token. self.prev_span = self.unnormalized_prev_token().span; self.expected_tokens.clear(); - // Check after each token. - self.process_potential_macro_variable(); } /// Advances the parser using provided token as a next one. Use this when @@ -924,9 +943,12 @@ impl<'a> Parser<'a> { /// Correct token kinds and spans need to be calculated instead. fn bump_with(&mut self, next: TokenKind, span: Span) { // Update the current and previous tokens. - let next_token = Token::new(next, span); - self.prev_token = mem::replace(&mut self.token, next_token); + self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); + self.token = Token::new(next, span); + if let Some(normalized_token) = Self::normalize_token(&self.token) { + self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); + } // Update fields derived from the previous token. self.prev_span = self.unnormalized_prev_token().span.with_hi(span.lo()); @@ -1066,39 +1088,6 @@ impl<'a> Parser<'a> { } } - pub fn process_potential_macro_variable(&mut self) { - let normalized_token = match self.token.kind { - token::Dollar - if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) => - { - self.bump(); - let name = match self.token.kind { - token::Ident(name, _) => name, - _ => unreachable!(), - }; - let span = self.prev_span.to(self.token.span); - self.struct_span_err(span, &format!("unknown macro variable `{}`", name)) - .span_label(span, "unknown macro variable") - .emit(); - self.bump(); - return; - } - token::Interpolated(ref nt) => { - // Interpolated identifier and lifetime tokens are replaced with usual identifier - // and lifetime tokens, so the former are never encountered during normal parsing. - match **nt { - token::NtIdent(ident, is_raw) => { - Token::new(token::Ident(ident.name, is_raw), ident.span) - } - token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span), - _ => return, - } - } - _ => return, - }; - self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); - } - /// Parses a single token tree from the input. pub fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { |
