]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/literal.rs
move unescape module to rustc_lexer
[rust.git] / src / libsyntax / parse / literal.rs
1 //! Code related to parsing literals.
2
3 use crate::ast::{self, Lit, LitKind};
4 use crate::parse::parser::Parser;
5 use crate::parse::PResult;
6 use crate::parse::token::{self, Token, TokenKind};
7 use crate::print::pprust;
8 use crate::symbol::{kw, sym, Symbol};
9 use crate::tokenstream::{TokenStream, TokenTree};
10
11 use errors::{Applicability, Handler};
12 use log::debug;
13 use rustc_data_structures::sync::Lrc;
14 use syntax_pos::Span;
15 use rustc_lexer::unescape::{unescape_char, unescape_byte};
16 use rustc_lexer::unescape::{unescape_str, unescape_byte_str};
17 use rustc_lexer::unescape::{unescape_raw_str, unescape_raw_byte_str};
18
19 use std::ascii;
20
21 crate enum LitError {
22     NotLiteral,
23     LexerError,
24     InvalidSuffix,
25     InvalidIntSuffix,
26     InvalidFloatSuffix,
27     NonDecimalFloat(u32),
28     IntTooLarge,
29 }
30
31 impl LitError {
32     fn report(&self, diag: &Handler, lit: token::Lit, span: Span) {
33         let token::Lit { kind, suffix, .. } = lit;
34         match *self {
35             // `NotLiteral` is not an error by itself, so we don't report
36             // it and give the parser opportunity to try something else.
37             LitError::NotLiteral => {}
38             // `LexerError` *is* an error, but it was already reported
39             // by lexer, so here we don't report it the second time.
40             LitError::LexerError => {}
41             LitError::InvalidSuffix => {
42                 expect_no_suffix(
43                     diag, span, &format!("{} {} literal", kind.article(), kind.descr()), suffix
44                 );
45             }
46             LitError::InvalidIntSuffix => {
47                 let suf = suffix.expect("suffix error with no suffix").as_str();
48                 if looks_like_width_suffix(&['i', 'u'], &suf) {
49                     // If it looks like a width, try to be helpful.
50                     let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
51                     diag.struct_span_err(span, &msg)
52                         .help("valid widths are 8, 16, 32, 64 and 128")
53                         .emit();
54                 } else {
55                     let msg = format!("invalid suffix `{}` for integer literal", suf);
56                     diag.struct_span_err(span, &msg)
57                         .span_label(span, format!("invalid suffix `{}`", suf))
58                         .help("the suffix must be one of the integral types (`u32`, `isize`, etc)")
59                         .emit();
60                 }
61             }
62             LitError::InvalidFloatSuffix => {
63                 let suf = suffix.expect("suffix error with no suffix").as_str();
64                 if looks_like_width_suffix(&['f'], &suf) {
65                     // If it looks like a width, try to be helpful.
66                     let msg = format!("invalid width `{}` for float literal", &suf[1..]);
67                     diag.struct_span_err(span, &msg)
68                         .help("valid widths are 32 and 64")
69                         .emit();
70                 } else {
71                     let msg = format!("invalid suffix `{}` for float literal", suf);
72                     diag.struct_span_err(span, &msg)
73                         .span_label(span, format!("invalid suffix `{}`", suf))
74                         .help("valid suffixes are `f32` and `f64`")
75                         .emit();
76                 }
77             }
78             LitError::NonDecimalFloat(base) => {
79                 let descr = match base {
80                     16 => "hexadecimal",
81                     8 => "octal",
82                     2 => "binary",
83                     _ => unreachable!(),
84                 };
85                 diag.struct_span_err(span, &format!("{} float literal is not supported", descr))
86                     .span_label(span, "not supported")
87                     .emit();
88             }
89             LitError::IntTooLarge => {
90                 diag.struct_span_err(span, "integer literal is too large")
91                     .emit();
92             }
93         }
94     }
95 }
96
97 impl LitKind {
98     /// Converts literal token into a semantic literal.
99     fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
100         let token::Lit { kind, symbol, suffix } = lit;
101         if suffix.is_some() && !kind.may_have_suffix() {
102             return Err(LitError::InvalidSuffix);
103         }
104
105         Ok(match kind {
106             token::Bool => {
107                 assert!(symbol == kw::True || symbol == kw::False);
108                 LitKind::Bool(symbol == kw::True)
109             }
110             token::Byte => return unescape_byte(&symbol.as_str())
111                 .map(LitKind::Byte).map_err(|_| LitError::LexerError),
112             token::Char => return unescape_char(&symbol.as_str())
113                 .map(LitKind::Char).map_err(|_| LitError::LexerError),
114
115             // There are some valid suffixes for integer and float literals,
116             // so all the handling is done internally.
117             token::Integer => return integer_lit(symbol, suffix),
118             token::Float => return float_lit(symbol, suffix),
119
120             token::Str => {
121                 // If there are no characters requiring special treatment we can
122                 // reuse the symbol from the token. Otherwise, we must generate a
123                 // new symbol because the string in the LitKind is different to the
124                 // string in the token.
125                 let s = symbol.as_str();
126                 let symbol = if s.contains(&['\\', '\r'][..]) {
127                     let mut buf = String::with_capacity(s.len());
128                     let mut error = Ok(());
129                     unescape_str(&s, &mut |_, unescaped_char| {
130                         match unescaped_char {
131                             Ok(c) => buf.push(c),
132                             Err(_) => error = Err(LitError::LexerError),
133                         }
134                     });
135                     error?;
136                     Symbol::intern(&buf)
137                 } else {
138                     symbol
139                 };
140                 LitKind::Str(symbol, ast::StrStyle::Cooked)
141             }
142             token::StrRaw(n) => {
143                 // Ditto.
144                 let s = symbol.as_str();
145                 let symbol = if s.contains('\r') {
146                     let mut buf = String::with_capacity(s.len());
147                     let mut error = Ok(());
148                     unescape_raw_str(&s, &mut |_, unescaped_char| {
149                         match unescaped_char {
150                             Ok(c) => buf.push(c),
151                             Err(_) => error = Err(LitError::LexerError),
152                         }
153                     });
154                     error?;
155                     buf.shrink_to_fit();
156                     Symbol::intern(&buf)
157                 } else {
158                     symbol
159                 };
160                 LitKind::Str(symbol, ast::StrStyle::Raw(n))
161             }
162             token::ByteStr => {
163                 let s = symbol.as_str();
164                 let mut buf = Vec::with_capacity(s.len());
165                 let mut error = Ok(());
166                 unescape_byte_str(&s, &mut |_, unescaped_byte| {
167                     match unescaped_byte {
168                         Ok(c) => buf.push(c),
169                         Err(_) => error = Err(LitError::LexerError),
170                     }
171                 });
172                 error?;
173                 buf.shrink_to_fit();
174                 LitKind::ByteStr(Lrc::new(buf))
175             }
176             token::ByteStrRaw(_) => {
177                 let s = symbol.as_str();
178                 let bytes = if s.contains('\r') {
179                     let mut buf = Vec::with_capacity(s.len());
180                     let mut error = Ok(());
181                     unescape_raw_byte_str(&s, &mut |_, unescaped_byte| {
182                         match unescaped_byte {
183                             Ok(c) => buf.push(c),
184                             Err(_) => error = Err(LitError::LexerError),
185                         }
186                     });
187                     error?;
188                     buf.shrink_to_fit();
189                     buf
190                 } else {
191                     symbol.to_string().into_bytes()
192                 };
193
194                 LitKind::ByteStr(Lrc::new(bytes))
195             },
196             token::Err => LitKind::Err(symbol),
197         })
198     }
199
200     /// Attempts to recover a token from semantic literal.
201     /// This function is used when the original token doesn't exist (e.g. the literal is created
202     /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
203     pub fn to_lit_token(&self) -> token::Lit {
204         let (kind, symbol, suffix) = match *self {
205             LitKind::Str(symbol, ast::StrStyle::Cooked) => {
206                 // Don't re-intern unless the escaped string is different.
207                 let s = &symbol.as_str();
208                 let escaped = s.escape_default().to_string();
209                 let symbol = if escaped == *s { symbol } else { Symbol::intern(&escaped) };
210                 (token::Str, symbol, None)
211             }
212             LitKind::Str(symbol, ast::StrStyle::Raw(n)) => {
213                 (token::StrRaw(n), symbol, None)
214             }
215             LitKind::ByteStr(ref bytes) => {
216                 let string = bytes.iter().cloned().flat_map(ascii::escape_default)
217                     .map(Into::<char>::into).collect::<String>();
218                 (token::ByteStr, Symbol::intern(&string), None)
219             }
220             LitKind::Byte(byte) => {
221                 let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
222                 (token::Byte, Symbol::intern(&string), None)
223             }
224             LitKind::Char(ch) => {
225                 let string: String = ch.escape_default().map(Into::<char>::into).collect();
226                 (token::Char, Symbol::intern(&string), None)
227             }
228             LitKind::Int(n, ty) => {
229                 let suffix = match ty {
230                     ast::LitIntType::Unsigned(ty) => Some(ty.to_symbol()),
231                     ast::LitIntType::Signed(ty) => Some(ty.to_symbol()),
232                     ast::LitIntType::Unsuffixed => None,
233                 };
234                 (token::Integer, sym::integer(n), suffix)
235             }
236             LitKind::Float(symbol, ty) => {
237                 (token::Float, symbol, Some(ty.to_symbol()))
238             }
239             LitKind::FloatUnsuffixed(symbol) => {
240                 (token::Float, symbol, None)
241             }
242             LitKind::Bool(value) => {
243                 let symbol = if value { kw::True } else { kw::False };
244                 (token::Bool, symbol, None)
245             }
246             LitKind::Err(symbol) => {
247                 (token::Err, symbol, None)
248             }
249         };
250
251         token::Lit::new(kind, symbol, suffix)
252     }
253 }
254
255 impl Lit {
256     /// Converts literal token into an AST literal.
257     fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
258         Ok(Lit { token, node: LitKind::from_lit_token(token)?, span })
259     }
260
261     /// Converts arbitrary token into an AST literal.
262     crate fn from_token(token: &Token) -> Result<Lit, LitError> {
263         let lit = match token.kind {
264             token::Ident(name, false) if name == kw::True || name == kw::False =>
265                 token::Lit::new(token::Bool, name, None),
266             token::Literal(lit) =>
267                 lit,
268             token::Interpolated(ref nt) => {
269                 if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
270                     if let ast::ExprKind::Lit(lit) = &expr.node {
271                         return Ok(lit.clone());
272                     }
273                 }
274                 return Err(LitError::NotLiteral);
275             }
276             _ => return Err(LitError::NotLiteral)
277         };
278
279         Lit::from_lit_token(lit, token.span)
280     }
281
282     /// Attempts to recover an AST literal from semantic literal.
283     /// This function is used when the original token doesn't exist (e.g. the literal is created
284     /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
285     pub fn from_lit_kind(node: LitKind, span: Span) -> Lit {
286         Lit { token: node.to_lit_token(), node, span }
287     }
288
289     /// Losslessly convert an AST literal into a token stream.
290     crate fn tokens(&self) -> TokenStream {
291         let token = match self.token.kind {
292             token::Bool => token::Ident(self.token.symbol, false),
293             _ => token::Literal(self.token),
294         };
295         TokenTree::token(token, self.span).into()
296     }
297 }
298
299 impl<'a> Parser<'a> {
300     /// Matches `lit = true | false | token_lit`.
301     crate fn parse_lit(&mut self) -> PResult<'a, Lit> {
302         let mut recovered = None;
303         if self.token == token::Dot {
304             // Attempt to recover `.4` as `0.4`.
305             recovered = self.look_ahead(1, |next_token| {
306                 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix })
307                         = next_token.kind {
308                     if self.token.span.hi() == next_token.span.lo() {
309                         let s = String::from("0.") + &symbol.as_str();
310                         let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
311                         return Some(Token::new(kind, self.token.span.to(next_token.span)));
312                     }
313                 }
314                 None
315             });
316             if let Some(token) = &recovered {
317                 self.bump();
318                 self.diagnostic()
319                     .struct_span_err(token.span, "float literals must have an integer part")
320                     .span_suggestion(
321                         token.span,
322                         "must have an integer part",
323                         pprust::token_to_string(token),
324                         Applicability::MachineApplicable,
325                     )
326                     .emit();
327             }
328         }
329
330         let token = recovered.as_ref().unwrap_or(&self.token);
331         match Lit::from_token(token) {
332             Ok(lit) => {
333                 self.bump();
334                 Ok(lit)
335             }
336             Err(LitError::NotLiteral) => {
337                 let msg = format!("unexpected token: {}", self.this_token_descr());
338                 Err(self.span_fatal(token.span, &msg))
339             }
340             Err(err) => {
341                 let (lit, span) = (token.expect_lit(), token.span);
342                 self.bump();
343                 err.report(&self.sess.span_diagnostic, lit, span);
344                 // Pack possible quotes and prefixes from the original literal into
345                 // the error literal's symbol so they can be pretty-printed faithfully.
346                 let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
347                 let symbol = Symbol::intern(&suffixless_lit.to_string());
348                 let lit = token::Lit::new(token::Err, symbol, lit.suffix);
349                 Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
350             }
351         }
352     }
353 }
354
355 crate fn expect_no_suffix(diag: &Handler, sp: Span, kind: &str, suffix: Option<Symbol>) {
356     if let Some(suf) = suffix {
357         let mut err = if kind == "a tuple index" &&
358                          [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) {
359             // #59553: warn instead of reject out of hand to allow the fix to percolate
360             // through the ecosystem when people fix their macros
361             let mut err = diag.struct_span_warn(
362                 sp,
363                 &format!("suffixes on {} are invalid", kind),
364             );
365             err.note(&format!(
366                 "`{}` is *temporarily* accepted on tuple index fields as it was \
367                     incorrectly accepted on stable for a few releases",
368                 suf,
369             ));
370             err.help(
371                 "on proc macros, you'll want to use `syn::Index::from` or \
372                     `proc_macro::Literal::*_unsuffixed` for code that will desugar \
373                     to tuple field access",
374             );
375             err.note(
376                 "for more context, see https://github.com/rust-lang/rust/issues/60210",
377             );
378             err
379         } else {
380             diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
381         };
382         err.span_label(sp, format!("invalid suffix `{}`", suf));
383         err.emit();
384     }
385 }
386
387 // Checks if `s` looks like i32 or u1234 etc.
388 fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
389     s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
390 }
391
392 fn strip_underscores(symbol: Symbol) -> Symbol {
393     // Do not allocate a new string unless necessary.
394     let s = symbol.as_str();
395     if s.contains('_') {
396         let mut s = s.to_string();
397         s.retain(|c| c != '_');
398         return Symbol::intern(&s);
399     }
400     symbol
401 }
402
403 fn filtered_float_lit(symbol: Symbol, suffix: Option<Symbol>, base: u32)
404                       -> Result<LitKind, LitError> {
405     debug!("filtered_float_lit: {:?}, {:?}, {:?}", symbol, suffix, base);
406     if base != 10 {
407         return Err(LitError::NonDecimalFloat(base));
408     }
409     Ok(match suffix {
410         Some(suf) => match suf {
411             sym::f32 => LitKind::Float(symbol, ast::FloatTy::F32),
412             sym::f64 => LitKind::Float(symbol, ast::FloatTy::F64),
413             _ => return Err(LitError::InvalidFloatSuffix),
414         }
415         None => LitKind::FloatUnsuffixed(symbol)
416     })
417 }
418
419 fn float_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
420     debug!("float_lit: {:?}, {:?}", symbol, suffix);
421     filtered_float_lit(strip_underscores(symbol), suffix, 10)
422 }
423
424 fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
425     debug!("integer_lit: {:?}, {:?}", symbol, suffix);
426     let symbol = strip_underscores(symbol);
427     let s = symbol.as_str();
428
429     let mut base = 10;
430     if s.len() > 1 && s.as_bytes()[0] == b'0' {
431         match s.as_bytes()[1] {
432             b'x' => base = 16,
433             b'o' => base = 8,
434             b'b' => base = 2,
435             _ => {}
436         }
437     }
438
439     let ty = match suffix {
440         Some(suf) => match suf {
441             sym::isize => ast::LitIntType::Signed(ast::IntTy::Isize),
442             sym::i8  => ast::LitIntType::Signed(ast::IntTy::I8),
443             sym::i16 => ast::LitIntType::Signed(ast::IntTy::I16),
444             sym::i32 => ast::LitIntType::Signed(ast::IntTy::I32),
445             sym::i64 => ast::LitIntType::Signed(ast::IntTy::I64),
446             sym::i128 => ast::LitIntType::Signed(ast::IntTy::I128),
447             sym::usize => ast::LitIntType::Unsigned(ast::UintTy::Usize),
448             sym::u8  => ast::LitIntType::Unsigned(ast::UintTy::U8),
449             sym::u16 => ast::LitIntType::Unsigned(ast::UintTy::U16),
450             sym::u32 => ast::LitIntType::Unsigned(ast::UintTy::U32),
451             sym::u64 => ast::LitIntType::Unsigned(ast::UintTy::U64),
452             sym::u128 => ast::LitIntType::Unsigned(ast::UintTy::U128),
453             // `1f64` and `2f32` etc. are valid float literals, and
454             // `fxxx` looks more like an invalid float literal than invalid integer literal.
455             _ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base),
456             _ => return Err(LitError::InvalidIntSuffix),
457         }
458         _ => ast::LitIntType::Unsuffixed
459     };
460
461     let s = &s[if base != 10 { 2 } else { 0 } ..];
462     u128::from_str_radix(s, base).map(|i| LitKind::Int(i, ty)).map_err(|_| {
463         // Small bases are lexed as if they were base 10, e.g, the string
464         // might be `0b10201`. This will cause the conversion above to fail,
465         // but these kinds of errors are already reported by the lexer.
466         let from_lexer =
467             base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
468         if from_lexer { LitError::LexerError } else { LitError::IntTooLarge }
469     })
470 }