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