1 //! Code related to parsing literals.
3 use crate::ast::{self, Ident, Lit, LitKind};
4 use crate::parse::parser::Parser;
5 use crate::parse::PResult;
6 use crate::parse::token::{self, Token};
7 use crate::parse::unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte};
8 use crate::print::pprust;
9 use crate::symbol::{kw, Symbol};
10 use crate::tokenstream::{TokenStream, TokenTree};
12 use errors::{Applicability, Handler};
14 use rustc_data_structures::sync::Lrc;
20 ($opt_diag:expr, |$span:ident, $diag:ident| $($body:tt)*) => {
22 Some(($span, $diag)) => { $($body)* }
29 /// Converts literal token with a suffix into a semantic literal.
30 /// Works speculatively and may return `None` if diagnostic handler is not passed.
31 /// If diagnostic handler is passed, always returns `Some`,
32 /// possibly after reporting non-fatal errors and recovery.
36 diag: Option<(Span, &Handler)>
37 ) -> Option<LitKind> {
38 if suf.is_some() && !lit.may_have_suffix() {
39 err!(diag, |span, diag| {
40 expect_no_suffix(span, diag, &format!("a {}", lit.literal_name()), suf)
46 assert!(i == kw::True || i == kw::False);
47 LitKind::Bool(i == kw::True)
50 match unescape_byte(&i.as_str()) {
51 Ok(c) => LitKind::Byte(c),
52 Err(_) => LitKind::Err(i),
56 match unescape_char(&i.as_str()) {
57 Ok(c) => LitKind::Char(c),
58 Err(_) => LitKind::Err(i),
61 token::Err(i) => LitKind::Err(i),
63 // There are some valid suffixes for integer and float literals,
64 // so all the handling is done internally.
65 token::Integer(s) => return integer_lit(&s.as_str(), suf, diag),
66 token::Float(s) => return float_lit(&s.as_str(), suf, diag),
68 token::Str_(mut sym) => {
69 // If there are no characters requiring special treatment we can
70 // reuse the symbol from the Token. Otherwise, we must generate a
71 // new symbol because the string in the LitKind is different to the
72 // string in the Token.
73 let mut has_error = false;
74 let s = &sym.as_str();
75 if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') {
76 let mut buf = String::with_capacity(s.len());
77 unescape_str(s, &mut |_, unescaped_char| {
78 match unescaped_char {
80 Err(_) => has_error = true,
84 return Some(LitKind::Err(sym));
86 sym = Symbol::intern(&buf)
89 LitKind::Str(sym, ast::StrStyle::Cooked)
91 token::StrRaw(mut sym, n) => {
93 let s = &sym.as_str();
95 sym = Symbol::intern(&raw_str_lit(s));
97 LitKind::Str(sym, ast::StrStyle::Raw(n))
99 token::ByteStr(i) => {
101 let mut buf = Vec::with_capacity(s.len());
102 let mut has_error = false;
103 unescape_byte_str(s, &mut |_, unescaped_byte| {
104 match unescaped_byte {
105 Ok(c) => buf.push(c),
106 Err(_) => has_error = true,
110 return Some(LitKind::Err(i));
113 LitKind::ByteStr(Lrc::new(buf))
115 token::ByteStrRaw(i, _) => {
116 LitKind::ByteStr(Lrc::new(i.to_string().into_bytes()))
121 /// Attempts to recover a token from semantic literal.
122 /// This function is used when the original token doesn't exist (e.g. the literal is created
123 /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
124 pub fn to_lit_token(&self) -> (token::Lit, Option<Symbol>) {
126 LitKind::Str(string, ast::StrStyle::Cooked) => {
127 let escaped = string.as_str().escape_default().to_string();
128 (token::Lit::Str_(Symbol::intern(&escaped)), None)
130 LitKind::Str(string, ast::StrStyle::Raw(n)) => {
131 (token::Lit::StrRaw(string, n), None)
133 LitKind::ByteStr(ref bytes) => {
134 let string = bytes.iter().cloned().flat_map(ascii::escape_default)
135 .map(Into::<char>::into).collect::<String>();
136 (token::Lit::ByteStr(Symbol::intern(&string)), None)
138 LitKind::Byte(byte) => {
139 let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
140 (token::Lit::Byte(Symbol::intern(&string)), None)
142 LitKind::Char(ch) => {
143 let string: String = ch.escape_default().map(Into::<char>::into).collect();
144 (token::Lit::Char(Symbol::intern(&string)), None)
146 LitKind::Int(n, ty) => {
147 let suffix = match ty {
148 ast::LitIntType::Unsigned(ty) => Some(Symbol::intern(ty.ty_to_string())),
149 ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())),
150 ast::LitIntType::Unsuffixed => None,
152 (token::Lit::Integer(Symbol::intern(&n.to_string())), suffix)
154 LitKind::Float(symbol, ty) => {
155 (token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string())))
157 LitKind::FloatUnsuffixed(symbol) => (token::Lit::Float(symbol), None),
158 LitKind::Bool(value) => {
159 let kw = if value { kw::True } else { kw::False };
160 (token::Lit::Bool(kw), None)
162 LitKind::Err(val) => (token::Lit::Err(val), None),
168 /// Converts literal token with a suffix into an AST literal.
169 /// Works speculatively and may return `None` if diagnostic handler is not passed.
170 /// If diagnostic handler is passed, may return `Some`,
171 /// possibly after reporting non-fatal errors and recovery, or `None` for irrecoverable errors.
173 token: &token::Token,
175 diag: Option<(Span, &Handler)>,
177 let (token, suffix) = match *token {
178 token::Ident(ident, false) if ident.name == kw::True || ident.name == kw::False =>
179 (token::Bool(ident.name), None),
180 token::Literal(token, suffix) =>
182 token::Interpolated(ref nt) => {
183 if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
184 if let ast::ExprKind::Lit(lit) = &expr.node {
185 return Some(lit.clone());
193 let node = LitKind::from_lit_token(token, suffix, diag)?;
194 Some(Lit { node, token, suffix, span })
197 /// Attempts to recover an AST literal from semantic literal.
198 /// This function is used when the original token doesn't exist (e.g. the literal is created
199 /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
200 pub fn from_lit_kind(node: LitKind, span: Span) -> Lit {
201 let (token, suffix) = node.to_lit_token();
202 Lit { node, token, suffix, span }
205 /// Losslessly convert an AST literal into a token stream.
206 crate fn tokens(&self) -> TokenStream {
207 let token = match self.token {
208 token::Bool(symbol) => Token::Ident(Ident::with_empty_ctxt(symbol), false),
209 token => Token::Literal(token, self.suffix),
211 TokenTree::Token(self.span, token).into()
215 impl<'a> Parser<'a> {
216 /// Matches `lit = true | false | token_lit`.
217 crate fn parse_lit(&mut self) -> PResult<'a, Lit> {
218 let diag = Some((self.span, &self.sess.span_diagnostic));
219 if let Some(lit) = Lit::from_token(&self.token, self.span, diag) {
222 } else if self.token == token::Dot {
223 // Recover `.4` as `0.4`.
224 let recovered = self.look_ahead(1, |t| {
225 if let token::Literal(token::Integer(val), suf) = *t {
226 let next_span = self.look_ahead_span(1);
227 if self.span.hi() == next_span.lo() {
228 let sym = String::from("0.") + &val.as_str();
229 let token = token::Literal(token::Float(Symbol::intern(&sym)), suf);
230 return Some((token, self.span.to(next_span)));
235 if let Some((token, span)) = recovered {
237 .struct_span_err(span, "float literals must have an integer part")
240 "must have an integer part",
241 pprust::token_to_string(&token),
242 Applicability::MachineApplicable,
245 let diag = Some((span, &self.sess.span_diagnostic));
246 if let Some(lit) = Lit::from_token(&token, span, diag) {
254 Err(self.span_fatal(self.span, &format!("unexpected token: {}", self.this_token_descr())))
258 crate fn expect_no_suffix(sp: Span, diag: &Handler, kind: &str, suffix: Option<ast::Name>) {
260 None => {/* everything ok */}
262 let text = suf.as_str();
264 diag.span_bug(sp, "found empty literal suffix in Some")
266 let mut err = if kind == "a tuple index" &&
267 ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str())
269 // #59553: warn instead of reject out of hand to allow the fix to percolate
270 // through the ecosystem when people fix their macros
271 let mut err = diag.struct_span_warn(
273 &format!("suffixes on {} are invalid", kind),
276 "`{}` is *temporarily* accepted on tuple index fields as it was \
277 incorrectly accepted on stable for a few releases",
281 "on proc macros, you'll want to use `syn::Index::from` or \
282 `proc_macro::Literal::*_unsuffixed` for code that will desugar \
283 to tuple field access",
286 "for more context, see https://github.com/rust-lang/rust/issues/60210",
290 diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
292 err.span_label(sp, format!("invalid suffix `{}`", text));
298 /// Parses a string representing a raw string literal into its final form. The
299 /// only operation this does is convert embedded CRLF into a single LF.
300 fn raw_str_lit(lit: &str) -> String {
301 debug!("raw_str_lit: given {}", lit.escape_default());
302 let mut res = String::with_capacity(lit.len());
304 let mut chars = lit.chars().peekable();
305 while let Some(c) = chars.next() {
307 if *chars.peek().unwrap() != '\n' {
308 panic!("lexer accepted bare CR");
321 // check if `s` looks like i32 or u1234 etc.
322 fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
323 s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
326 fn filtered_float_lit(data: Symbol, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
328 debug!("filtered_float_lit: {}, {:?}", data, suffix);
329 let suffix = match suffix {
330 Some(suffix) => suffix,
331 None => return Some(LitKind::FloatUnsuffixed(data)),
334 Some(match &*suffix.as_str() {
335 "f32" => LitKind::Float(data, ast::FloatTy::F32),
336 "f64" => LitKind::Float(data, ast::FloatTy::F64),
338 err!(diag, |span, diag| {
339 if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) {
340 // if it looks like a width, lets try to be helpful.
341 let msg = format!("invalid width `{}` for float literal", &suf[1..]);
342 diag.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit()
344 let msg = format!("invalid suffix `{}` for float literal", suf);
345 diag.struct_span_err(span, &msg)
346 .span_label(span, format!("invalid suffix `{}`", suf))
347 .help("valid suffixes are `f32` and `f64`")
352 LitKind::FloatUnsuffixed(data)
356 fn float_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
358 debug!("float_lit: {:?}, {:?}", s, suffix);
359 // FIXME #2252: bounds checking float literals is deferred until trans
361 // Strip underscores without allocating a new String unless necessary.
363 let s = if s.chars().any(|c| c == '_') {
364 s2 = s.chars().filter(|&c| c != '_').collect::<String>();
370 filtered_float_lit(Symbol::intern(s), suffix, diag)
373 fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
375 // s can only be ascii, byte indexing is fine
377 // Strip underscores without allocating a new String unless necessary.
379 let mut s = if s.chars().any(|c| c == '_') {
380 s2 = s.chars().filter(|&c| c != '_').collect::<String>();
386 debug!("integer_lit: {}, {:?}", s, suffix);
390 let mut ty = ast::LitIntType::Unsuffixed;
392 if s.starts_with('0') && s.len() > 1 {
393 match s.as_bytes()[1] {
401 // 1f64 and 2f32 etc. are valid float literals.
402 if let Some(suf) = suffix {
403 if looks_like_width_suffix(&['f'], &suf.as_str()) {
404 let err = match base {
405 16 => Some("hexadecimal float literal is not supported"),
406 8 => Some("octal float literal is not supported"),
407 2 => Some("binary float literal is not supported"),
410 if let Some(err) = err {
411 err!(diag, |span, diag| {
412 diag.struct_span_err(span, err)
413 .span_label(span, "not supported")
417 return filtered_float_lit(Symbol::intern(s), Some(suf), diag)
425 if let Some(suf) = suffix {
426 if suf.as_str().is_empty() {
427 err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some"));
429 ty = match &*suf.as_str() {
430 "isize" => ast::LitIntType::Signed(ast::IntTy::Isize),
431 "i8" => ast::LitIntType::Signed(ast::IntTy::I8),
432 "i16" => ast::LitIntType::Signed(ast::IntTy::I16),
433 "i32" => ast::LitIntType::Signed(ast::IntTy::I32),
434 "i64" => ast::LitIntType::Signed(ast::IntTy::I64),
435 "i128" => ast::LitIntType::Signed(ast::IntTy::I128),
436 "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize),
437 "u8" => ast::LitIntType::Unsigned(ast::UintTy::U8),
438 "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
439 "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
440 "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
441 "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128),
443 // i<digits> and u<digits> look like widths, so lets
444 // give an error message along those lines
445 err!(diag, |span, diag| {
446 if looks_like_width_suffix(&['i', 'u'], suf) {
447 let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
448 diag.struct_span_err(span, &msg)
449 .help("valid widths are 8, 16, 32, 64 and 128")
452 let msg = format!("invalid suffix `{}` for numeric literal", suf);
453 diag.struct_span_err(span, &msg)
454 .span_label(span, format!("invalid suffix `{}`", suf))
455 .help("the suffix must be one of the integral types \
456 (`u32`, `isize`, etc)")
466 debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \
467 string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix);
469 Some(match u128::from_str_radix(s, base) {
470 Ok(r) => LitKind::Int(r, ty),
472 // small bases are lexed as if they were base 10, e.g, the string
473 // might be `0b10201`. This will cause the conversion above to fail,
474 // but these cases have errors in the lexer: we don't want to emit
475 // two errors, and we especially don't want to emit this error since
476 // it isn't necessarily true.
477 let already_errored = base < 10 &&
478 s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
480 if !already_errored {
481 err!(diag, |span, diag| diag.span_err(span, "int literal is too large"));