From b85a3da421abad7d1936ec6e57e43c7b0ff10bd3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Nov 2019 15:32:41 +0300 Subject: [PATCH] parse: Support parsing optional literals Revert weird renaming of the former `LitError::report` --- src/librustc_parse/parser/expr.rs | 31 +++++++++++++++++++------------ src/librustc_parse/parser/item.rs | 2 +- src/librustc_parse/parser/mod.rs | 15 +++++++-------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index dadb91f8b3c..df2f6822465 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -778,13 +778,12 @@ impl<'a> Parser<'a> { macro_rules! parse_lit { () => { - match self.parse_lit() { - Ok(literal) => { + match self.parse_opt_lit() { + Some(literal) => { hi = self.prev_span; ex = ExprKind::Lit(literal); } - Err(mut err) => { - err.cancel(); + None => { return Err(self.expected_expression_found()); } } @@ -1074,11 +1073,20 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } - /// Matches `lit = true | false | token_lit`. pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { + self.parse_opt_lit().ok_or_else(|| { + let msg = format!("unexpected token: {}", self.this_token_descr()); + self.span_fatal(self.token.span, &msg) + }) + } + + /// Matches `lit = true | false | token_lit`. + /// Returns `None` if the next token is not a literal. + pub(super) fn parse_opt_lit(&mut self) -> Option { let mut recovered = None; if self.token == token::Dot { - // Attempt to recover `.4` as `0.4`. + // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where + // dot would follow an optional literal, so we do this unconditionally. recovered = self.look_ahead(1, |next_token| { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = next_token.kind { @@ -1107,11 +1115,10 @@ impl<'a> Parser<'a> { match Lit::from_token(token) { Ok(lit) => { self.bump(); - Ok(lit) + Some(lit) } Err(LitError::NotLiteral) => { - let msg = format!("unexpected token: {}", self.this_token_descr()); - Err(self.span_fatal(token.span, &msg)) + None } Err(err) => { let span = token.span; @@ -1120,18 +1127,18 @@ impl<'a> Parser<'a> { _ => unreachable!(), }; self.bump(); - self.error_literal_from_token(err, lit, span); + self.report_lit_error(err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); let symbol = Symbol::intern(&suffixless_lit.to_string()); let lit = token::Lit::new(token::Err, symbol, lit.suffix); - Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) + Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!())) } } } - fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) { + fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3b824dc939f..8e6df0fa4f3 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -105,7 +105,7 @@ impl<'a> Parser<'a> { return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } - let abi = self.parse_opt_abi()?; + let abi = self.parse_opt_abi(); if self.eat_keyword(kw::Fn) { // EXTERN FUNCTION ITEM diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 2b49091192c..7757e00020a 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1214,21 +1214,20 @@ impl<'a> Parser<'a> { /// Parses `extern string_literal?`. fn parse_extern(&mut self) -> PResult<'a, Extern> { Ok(if self.eat_keyword(kw::Extern) { - Extern::from_abi(self.parse_opt_abi()?) + Extern::from_abi(self.parse_opt_abi()) } else { Extern::None }) } /// Parses a string literal as an ABI spec. - fn parse_opt_abi(&mut self) -> PResult<'a, Option> { - if self.token.can_begin_literal_or_bool() { - let ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind } - = self.parse_lit()?; + fn parse_opt_abi(&mut self) -> Option { + if let Some(ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind }) + = self.parse_opt_lit() { match kind { - ast::LitKind::Str(symbol_unescaped, style) => return Ok(Some(StrLit { + ast::LitKind::Str(symbol_unescaped, style) => return Some(StrLit { style, symbol, suffix, span, symbol_unescaped, - })), + }), ast::LitKind::Err(_) => {} _ => { self.struct_span_err(span, "non-string ABI literal") @@ -1242,7 +1241,7 @@ impl<'a> Parser<'a> { } } } - Ok(None) + None } /// We are parsing `async fn`. If we are on Rust 2015, emit an error.