1 #[cfg(feature = "parsing")]
2 use crate::lookahead;
3 #[cfg(feature = "parsing")]
4 use crate::parse::{Parse, Parser};
5 use crate::{Error, Result};
6 #[cfg(feature = "printing")]
7 use proc_macro2::Ident;
8 #[cfg(feature = "parsing")]
9 use proc_macro2::TokenStream;
10 use proc_macro2::TokenTree;
11 use proc_macro2::{Literal, Span};
12 use std::fmt::{self, Display};
13 #[cfg(feature = "extra-traits")]
14 use std::hash::{Hash, Hasher};
15 use std::str::{self, FromStr};
16 
17 ast_enum_of_structs! {
18     /// A Rust literal such as a string or integer or boolean.
19     ///
20     /// # Syntax tree enum
21     ///
22     /// This type is a [syntax tree enum].
23     ///
24     /// [syntax tree enum]: crate::Expr#syntax-tree-enums
25     pub enum Lit {
26         /// A UTF-8 string literal: `"foo"`.
27         Str(LitStr),
28 
29         /// A byte string literal: `b"foo"`.
30         ByteStr(LitByteStr),
31 
32         /// A byte literal: `b'f'`.
33         Byte(LitByte),
34 
35         /// A character literal: `'a'`.
36         Char(LitChar),
37 
38         /// An integer literal: `1` or `1u16`.
39         Int(LitInt),
40 
41         /// A floating point literal: `1f64` or `1.0e10f64`.
42         ///
43         /// Must be finite. May not be infinte or NaN.
44         Float(LitFloat),
45 
46         /// A boolean literal: `true` or `false`.
47         Bool(LitBool),
48 
49         /// A raw token literal not interpreted by Syn.
50         Verbatim(Literal),
51     }
52 }
53 
54 ast_struct! {
55     /// A UTF-8 string literal: `"foo"`.
56     pub struct LitStr {
57         repr: Box<LitRepr>,
58     }
59 }
60 
61 ast_struct! {
62     /// A byte string literal: `b"foo"`.
63     pub struct LitByteStr {
64         repr: Box<LitRepr>,
65     }
66 }
67 
68 ast_struct! {
69     /// A byte literal: `b'f'`.
70     pub struct LitByte {
71         repr: Box<LitRepr>,
72     }
73 }
74 
75 ast_struct! {
76     /// A character literal: `'a'`.
77     pub struct LitChar {
78         repr: Box<LitRepr>,
79     }
80 }
81 
82 struct LitRepr {
83     token: Literal,
84     suffix: Box<str>,
85 }
86 
87 ast_struct! {
88     /// An integer literal: `1` or `1u16`.
89     pub struct LitInt {
90         repr: Box<LitIntRepr>,
91     }
92 }
93 
94 struct LitIntRepr {
95     token: Literal,
96     digits: Box<str>,
97     suffix: Box<str>,
98 }
99 
100 ast_struct! {
101     /// A floating point literal: `1f64` or `1.0e10f64`.
102     ///
103     /// Must be finite. May not be infinite or NaN.
104     pub struct LitFloat {
105         repr: Box<LitFloatRepr>,
106     }
107 }
108 
109 struct LitFloatRepr {
110     token: Literal,
111     digits: Box<str>,
112     suffix: Box<str>,
113 }
114 
115 ast_struct! {
116     /// A boolean literal: `true` or `false`.
117     pub struct LitBool {
118         pub value: bool,
119         pub span: Span,
120     }
121 }
122 
123 impl LitStr {
new(value: &str, span: Span) -> Self124     pub fn new(value: &str, span: Span) -> Self {
125         let mut token = Literal::string(value);
126         token.set_span(span);
127         LitStr {
128             repr: Box::new(LitRepr {
129                 token,
130                 suffix: Box::<str>::default(),
131             }),
132         }
133     }
134 
value(&self) -> String135     pub fn value(&self) -> String {
136         let repr = self.repr.token.to_string();
137         let (value, _suffix) = value::parse_lit_str(&repr);
138         String::from(value)
139     }
140 
141     /// Parse a syntax tree node from the content of this string literal.
142     ///
143     /// All spans in the syntax tree will point to the span of this `LitStr`.
144     ///
145     /// # Example
146     ///
147     /// ```
148     /// use proc_macro2::Span;
149     /// use syn::{Attribute, Error, Ident, Lit, Meta, MetaNameValue, Path, Result};
150     ///
151     /// // Parses the path from an attribute that looks like:
152     /// //
153     /// //     #[path = "a::b::c"]
154     /// //
155     /// // or returns `None` if the input is some other attribute.
156     /// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
157     ///     if !attr.path.is_ident("path") {
158     ///         return Ok(None);
159     ///     }
160     ///
161     ///     match attr.parse_meta()? {
162     ///         Meta::NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
163     ///             lit_str.parse().map(Some)
164     ///         }
165     ///         _ => {
166     ///             let message = "expected #[path = \"...\"]";
167     ///             Err(Error::new_spanned(attr, message))
168     ///         }
169     ///     }
170     /// }
171     /// ```
172     #[cfg(feature = "parsing")]
173     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
parse<T: Parse>(&self) -> Result<T>174     pub fn parse<T: Parse>(&self) -> Result<T> {
175         self.parse_with(T::parse)
176     }
177 
178     /// Invoke parser on the content of this string literal.
179     ///
180     /// All spans in the syntax tree will point to the span of this `LitStr`.
181     ///
182     /// # Example
183     ///
184     /// ```
185     /// # use proc_macro2::Span;
186     /// # use syn::{LitStr, Result};
187     /// #
188     /// # fn main() -> Result<()> {
189     /// #     let lit_str = LitStr::new("a::b::c", Span::call_site());
190     /// #
191     /// #     const IGNORE: &str = stringify! {
192     /// let lit_str: LitStr = /* ... */;
193     /// #     };
194     ///
195     /// // Parse a string literal like "a::b::c" into a Path, not allowing
196     /// // generic arguments on any of the path segments.
197     /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
198     /// #
199     /// #     Ok(())
200     /// # }
201     /// ```
202     #[cfg(feature = "parsing")]
203     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
parse_with<F: Parser>(&self, parser: F) -> Result<F::Output>204     pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
205         use proc_macro2::Group;
206 
207         // Token stream with every span replaced by the given one.
208         fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
209             stream
210                 .into_iter()
211                 .map(|token| respan_token_tree(token, span))
212                 .collect()
213         }
214 
215         // Token tree with every span replaced by the given one.
216         fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
217             match &mut token {
218                 TokenTree::Group(g) => {
219                     let stream = respan_token_stream(g.stream(), span);
220                     *g = Group::new(g.delimiter(), stream);
221                     g.set_span(span);
222                 }
223                 other => other.set_span(span),
224             }
225             token
226         }
227 
228         // Parse string literal into a token stream with every span equal to the
229         // original literal's span.
230         let mut tokens = crate::parse_str(&self.value())?;
231         tokens = respan_token_stream(tokens, self.span());
232 
233         parser.parse2(tokens)
234     }
235 
span(&self) -> Span236     pub fn span(&self) -> Span {
237         self.repr.token.span()
238     }
239 
set_span(&mut self, span: Span)240     pub fn set_span(&mut self, span: Span) {
241         self.repr.token.set_span(span)
242     }
243 
suffix(&self) -> &str244     pub fn suffix(&self) -> &str {
245         &self.repr.suffix
246     }
247 }
248 
249 impl LitByteStr {
new(value: &[u8], span: Span) -> Self250     pub fn new(value: &[u8], span: Span) -> Self {
251         let mut token = Literal::byte_string(value);
252         token.set_span(span);
253         LitByteStr {
254             repr: Box::new(LitRepr {
255                 token,
256                 suffix: Box::<str>::default(),
257             }),
258         }
259     }
260 
value(&self) -> Vec<u8>261     pub fn value(&self) -> Vec<u8> {
262         let repr = self.repr.token.to_string();
263         let (value, _suffix) = value::parse_lit_byte_str(&repr);
264         value
265     }
266 
span(&self) -> Span267     pub fn span(&self) -> Span {
268         self.repr.token.span()
269     }
270 
set_span(&mut self, span: Span)271     pub fn set_span(&mut self, span: Span) {
272         self.repr.token.set_span(span)
273     }
274 
suffix(&self) -> &str275     pub fn suffix(&self) -> &str {
276         &self.repr.suffix
277     }
278 }
279 
280 impl LitByte {
new(value: u8, span: Span) -> Self281     pub fn new(value: u8, span: Span) -> Self {
282         let mut token = Literal::u8_suffixed(value);
283         token.set_span(span);
284         LitByte {
285             repr: Box::new(LitRepr {
286                 token,
287                 suffix: Box::<str>::default(),
288             }),
289         }
290     }
291 
value(&self) -> u8292     pub fn value(&self) -> u8 {
293         let repr = self.repr.token.to_string();
294         let (value, _suffix) = value::parse_lit_byte(&repr);
295         value
296     }
297 
span(&self) -> Span298     pub fn span(&self) -> Span {
299         self.repr.token.span()
300     }
301 
set_span(&mut self, span: Span)302     pub fn set_span(&mut self, span: Span) {
303         self.repr.token.set_span(span)
304     }
305 
suffix(&self) -> &str306     pub fn suffix(&self) -> &str {
307         &self.repr.suffix
308     }
309 }
310 
311 impl LitChar {
new(value: char, span: Span) -> Self312     pub fn new(value: char, span: Span) -> Self {
313         let mut token = Literal::character(value);
314         token.set_span(span);
315         LitChar {
316             repr: Box::new(LitRepr {
317                 token,
318                 suffix: Box::<str>::default(),
319             }),
320         }
321     }
322 
value(&self) -> char323     pub fn value(&self) -> char {
324         let repr = self.repr.token.to_string();
325         let (value, _suffix) = value::parse_lit_char(&repr);
326         value
327     }
328 
span(&self) -> Span329     pub fn span(&self) -> Span {
330         self.repr.token.span()
331     }
332 
set_span(&mut self, span: Span)333     pub fn set_span(&mut self, span: Span) {
334         self.repr.token.set_span(span)
335     }
336 
suffix(&self) -> &str337     pub fn suffix(&self) -> &str {
338         &self.repr.suffix
339     }
340 }
341 
342 impl LitInt {
new(repr: &str, span: Span) -> Self343     pub fn new(repr: &str, span: Span) -> Self {
344         let (digits, suffix) = match value::parse_lit_int(repr) {
345             Some(parse) => parse,
346             None => panic!("Not an integer literal: `{}`", repr),
347         };
348 
349         let mut token = match value::to_literal(repr, &digits, &suffix) {
350             Some(token) => token,
351             None => panic!("Unsupported integer literal: `{}`", repr),
352         };
353 
354         token.set_span(span);
355         LitInt {
356             repr: Box::new(LitIntRepr {
357                 token,
358                 digits,
359                 suffix,
360             }),
361         }
362     }
363 
base10_digits(&self) -> &str364     pub fn base10_digits(&self) -> &str {
365         &self.repr.digits
366     }
367 
368     /// Parses the literal into a selected number type.
369     ///
370     /// This is equivalent to `lit.base10_digits().parse()` except that the
371     /// resulting errors will be correctly spanned to point to the literal token
372     /// in the macro input.
373     ///
374     /// ```
375     /// use syn::LitInt;
376     /// use syn::parse::{Parse, ParseStream, Result};
377     ///
378     /// struct Port {
379     ///     value: u16,
380     /// }
381     ///
382     /// impl Parse for Port {
383     ///     fn parse(input: ParseStream) -> Result<Self> {
384     ///         let lit: LitInt = input.parse()?;
385     ///         let value = lit.base10_parse::<u16>()?;
386     ///         Ok(Port { value })
387     ///     }
388     /// }
389     /// ```
base10_parse<N>(&self) -> Result<N> where N: FromStr, N::Err: Display,390     pub fn base10_parse<N>(&self) -> Result<N>
391     where
392         N: FromStr,
393         N::Err: Display,
394     {
395         self.base10_digits()
396             .parse()
397             .map_err(|err| Error::new(self.span(), err))
398     }
399 
suffix(&self) -> &str400     pub fn suffix(&self) -> &str {
401         &self.repr.suffix
402     }
403 
span(&self) -> Span404     pub fn span(&self) -> Span {
405         self.repr.token.span()
406     }
407 
set_span(&mut self, span: Span)408     pub fn set_span(&mut self, span: Span) {
409         self.repr.token.set_span(span)
410     }
411 }
412 
413 impl From<Literal> for LitInt {
from(token: Literal) -> Self414     fn from(token: Literal) -> Self {
415         let repr = token.to_string();
416         if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
417             LitInt {
418                 repr: Box::new(LitIntRepr {
419                     token,
420                     digits,
421                     suffix,
422                 }),
423             }
424         } else {
425             panic!("Not an integer literal: `{}`", repr);
426         }
427     }
428 }
429 
430 impl Display for LitInt {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result431     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
432         self.repr.token.fmt(formatter)
433     }
434 }
435 
436 impl LitFloat {
new(repr: &str, span: Span) -> Self437     pub fn new(repr: &str, span: Span) -> Self {
438         let (digits, suffix) = match value::parse_lit_float(repr) {
439             Some(parse) => parse,
440             None => panic!("Not a float literal: `{}`", repr),
441         };
442 
443         let mut token = match value::to_literal(repr, &digits, &suffix) {
444             Some(token) => token,
445             None => panic!("Unsupported float literal: `{}`", repr),
446         };
447 
448         token.set_span(span);
449         LitFloat {
450             repr: Box::new(LitFloatRepr {
451                 token,
452                 digits,
453                 suffix,
454             }),
455         }
456     }
457 
base10_digits(&self) -> &str458     pub fn base10_digits(&self) -> &str {
459         &self.repr.digits
460     }
461 
base10_parse<N>(&self) -> Result<N> where N: FromStr, N::Err: Display,462     pub fn base10_parse<N>(&self) -> Result<N>
463     where
464         N: FromStr,
465         N::Err: Display,
466     {
467         self.base10_digits()
468             .parse()
469             .map_err(|err| Error::new(self.span(), err))
470     }
471 
suffix(&self) -> &str472     pub fn suffix(&self) -> &str {
473         &self.repr.suffix
474     }
475 
span(&self) -> Span476     pub fn span(&self) -> Span {
477         self.repr.token.span()
478     }
479 
set_span(&mut self, span: Span)480     pub fn set_span(&mut self, span: Span) {
481         self.repr.token.set_span(span)
482     }
483 }
484 
485 impl From<Literal> for LitFloat {
from(token: Literal) -> Self486     fn from(token: Literal) -> Self {
487         let repr = token.to_string();
488         if let Some((digits, suffix)) = value::parse_lit_float(&repr) {
489             LitFloat {
490                 repr: Box::new(LitFloatRepr {
491                     token,
492                     digits,
493                     suffix,
494                 }),
495             }
496         } else {
497             panic!("Not a float literal: `{}`", repr);
498         }
499     }
500 }
501 
502 impl Display for LitFloat {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result503     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
504         self.repr.token.fmt(formatter)
505     }
506 }
507 
508 #[cfg(feature = "extra-traits")]
509 mod debug_impls {
510     use super::*;
511     use std::fmt::{self, Debug};
512 
513     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
514     impl Debug for LitStr {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result515         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
516             formatter
517                 .debug_struct("LitStr")
518                 .field("token", &format_args!("{}", self.repr.token))
519                 .finish()
520         }
521     }
522 
523     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
524     impl Debug for LitByteStr {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result525         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
526             formatter
527                 .debug_struct("LitByteStr")
528                 .field("token", &format_args!("{}", self.repr.token))
529                 .finish()
530         }
531     }
532 
533     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
534     impl Debug for LitByte {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result535         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
536             formatter
537                 .debug_struct("LitByte")
538                 .field("token", &format_args!("{}", self.repr.token))
539                 .finish()
540         }
541     }
542 
543     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
544     impl Debug for LitChar {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result545         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
546             formatter
547                 .debug_struct("LitChar")
548                 .field("token", &format_args!("{}", self.repr.token))
549                 .finish()
550         }
551     }
552 
553     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
554     impl Debug for LitInt {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result555         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
556             formatter
557                 .debug_struct("LitInt")
558                 .field("token", &format_args!("{}", self.repr.token))
559                 .finish()
560         }
561     }
562 
563     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
564     impl Debug for LitFloat {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result565         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
566             formatter
567                 .debug_struct("LitFloat")
568                 .field("token", &format_args!("{}", self.repr.token))
569                 .finish()
570         }
571     }
572 
573     #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
574     impl Debug for LitBool {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result575         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
576             formatter
577                 .debug_struct("LitBool")
578                 .field("value", &self.value)
579                 .finish()
580         }
581     }
582 }
583 
584 #[cfg(feature = "clone-impls")]
585 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
586 impl Clone for LitRepr {
clone(&self) -> Self587     fn clone(&self) -> Self {
588         LitRepr {
589             token: self.token.clone(),
590             suffix: self.suffix.clone(),
591         }
592     }
593 }
594 
595 #[cfg(feature = "clone-impls")]
596 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
597 impl Clone for LitIntRepr {
clone(&self) -> Self598     fn clone(&self) -> Self {
599         LitIntRepr {
600             token: self.token.clone(),
601             digits: self.digits.clone(),
602             suffix: self.suffix.clone(),
603         }
604     }
605 }
606 
607 #[cfg(feature = "clone-impls")]
608 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
609 impl Clone for LitFloatRepr {
clone(&self) -> Self610     fn clone(&self) -> Self {
611         LitFloatRepr {
612             token: self.token.clone(),
613             digits: self.digits.clone(),
614             suffix: self.suffix.clone(),
615         }
616     }
617 }
618 
619 macro_rules! lit_extra_traits {
620     ($ty:ident) => {
621         #[cfg(feature = "clone-impls")]
622         #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
623         impl Clone for $ty {
624             fn clone(&self) -> Self {
625                 $ty {
626                     repr: self.repr.clone(),
627                 }
628             }
629         }
630 
631         #[cfg(feature = "extra-traits")]
632         #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
633         impl PartialEq for $ty {
634             fn eq(&self, other: &Self) -> bool {
635                 self.repr.token.to_string() == other.repr.token.to_string()
636             }
637         }
638 
639         #[cfg(feature = "extra-traits")]
640         #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
641         impl Hash for $ty {
642             fn hash<H>(&self, state: &mut H)
643             where
644                 H: Hasher,
645             {
646                 self.repr.token.to_string().hash(state);
647             }
648         }
649 
650         #[cfg(feature = "parsing")]
651         #[doc(hidden)]
652         #[allow(non_snake_case)]
653         pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
654             match marker {}
655         }
656     };
657 }
658 
659 lit_extra_traits!(LitStr);
660 lit_extra_traits!(LitByteStr);
661 lit_extra_traits!(LitByte);
662 lit_extra_traits!(LitChar);
663 lit_extra_traits!(LitInt);
664 lit_extra_traits!(LitFloat);
665 
666 #[cfg(feature = "parsing")]
667 #[doc(hidden)]
668 #[allow(non_snake_case)]
LitBool(marker: lookahead::TokenMarker) -> LitBool669 pub fn LitBool(marker: lookahead::TokenMarker) -> LitBool {
670     match marker {}
671 }
672 
673 ast_enum! {
674     /// The style of a string literal, either plain quoted or a raw string like
675     /// `r##"data"##`.
676     pub enum StrStyle #no_visit {
677         /// An ordinary string like `"data"`.
678         Cooked,
679         /// A raw string like `r##"data"##`.
680         ///
681         /// The unsigned integer is the number of `#` symbols used.
682         Raw(usize),
683     }
684 }
685 
686 #[cfg(feature = "parsing")]
687 #[doc(hidden)]
688 #[allow(non_snake_case)]
Lit(marker: lookahead::TokenMarker) -> Lit689 pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
690     match marker {}
691 }
692 
693 #[cfg(feature = "parsing")]
694 pub mod parsing {
695     use super::*;
696     use crate::buffer::Cursor;
697     use crate::parse::{Parse, ParseStream, Result};
698     use proc_macro2::Punct;
699 
700     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
701     impl Parse for Lit {
parse(input: ParseStream) -> Result<Self>702         fn parse(input: ParseStream) -> Result<Self> {
703             input.step(|cursor| {
704                 if let Some((lit, rest)) = cursor.literal() {
705                     return Ok((Lit::new(lit), rest));
706                 }
707 
708                 if let Some((ident, rest)) = cursor.ident() {
709                     let value = ident == "true";
710                     if value || ident == "false" {
711                         let lit_bool = LitBool {
712                             value,
713                             span: ident.span(),
714                         };
715                         return Ok((Lit::Bool(lit_bool), rest));
716                     }
717                 }
718 
719                 if let Some((punct, rest)) = cursor.punct() {
720                     if punct.as_char() == '-' {
721                         if let Some((lit, rest)) = parse_negative_lit(punct, rest) {
722                             return Ok((lit, rest));
723                         }
724                     }
725                 }
726 
727                 Err(cursor.error("expected literal"))
728             })
729         }
730     }
731 
parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)>732     fn parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)> {
733         let (lit, rest) = cursor.literal()?;
734 
735         let mut span = neg.span();
736         span = span.join(lit.span()).unwrap_or(span);
737 
738         let mut repr = lit.to_string();
739         repr.insert(0, '-');
740 
741         if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
742             if let Some(mut token) = value::to_literal(&repr, &digits, &suffix) {
743                 token.set_span(span);
744                 return Some((
745                     Lit::Int(LitInt {
746                         repr: Box::new(LitIntRepr {
747                             token,
748                             digits,
749                             suffix,
750                         }),
751                     }),
752                     rest,
753                 ));
754             }
755         }
756 
757         let (digits, suffix) = value::parse_lit_float(&repr)?;
758         let mut token = value::to_literal(&repr, &digits, &suffix)?;
759         token.set_span(span);
760         Some((
761             Lit::Float(LitFloat {
762                 repr: Box::new(LitFloatRepr {
763                     token,
764                     digits,
765                     suffix,
766                 }),
767             }),
768             rest,
769         ))
770     }
771 
772     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
773     impl Parse for LitStr {
parse(input: ParseStream) -> Result<Self>774         fn parse(input: ParseStream) -> Result<Self> {
775             let head = input.fork();
776             match input.parse() {
777                 Ok(Lit::Str(lit)) => Ok(lit),
778                 _ => Err(head.error("expected string literal")),
779             }
780         }
781     }
782 
783     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
784     impl Parse for LitByteStr {
parse(input: ParseStream) -> Result<Self>785         fn parse(input: ParseStream) -> Result<Self> {
786             let head = input.fork();
787             match input.parse() {
788                 Ok(Lit::ByteStr(lit)) => Ok(lit),
789                 _ => Err(head.error("expected byte string literal")),
790             }
791         }
792     }
793 
794     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
795     impl Parse for LitByte {
parse(input: ParseStream) -> Result<Self>796         fn parse(input: ParseStream) -> Result<Self> {
797             let head = input.fork();
798             match input.parse() {
799                 Ok(Lit::Byte(lit)) => Ok(lit),
800                 _ => Err(head.error("expected byte literal")),
801             }
802         }
803     }
804 
805     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
806     impl Parse for LitChar {
parse(input: ParseStream) -> Result<Self>807         fn parse(input: ParseStream) -> Result<Self> {
808             let head = input.fork();
809             match input.parse() {
810                 Ok(Lit::Char(lit)) => Ok(lit),
811                 _ => Err(head.error("expected character literal")),
812             }
813         }
814     }
815 
816     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
817     impl Parse for LitInt {
parse(input: ParseStream) -> Result<Self>818         fn parse(input: ParseStream) -> Result<Self> {
819             let head = input.fork();
820             match input.parse() {
821                 Ok(Lit::Int(lit)) => Ok(lit),
822                 _ => Err(head.error("expected integer literal")),
823             }
824         }
825     }
826 
827     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
828     impl Parse for LitFloat {
parse(input: ParseStream) -> Result<Self>829         fn parse(input: ParseStream) -> Result<Self> {
830             let head = input.fork();
831             match input.parse() {
832                 Ok(Lit::Float(lit)) => Ok(lit),
833                 _ => Err(head.error("expected floating point literal")),
834             }
835         }
836     }
837 
838     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
839     impl Parse for LitBool {
parse(input: ParseStream) -> Result<Self>840         fn parse(input: ParseStream) -> Result<Self> {
841             let head = input.fork();
842             match input.parse() {
843                 Ok(Lit::Bool(lit)) => Ok(lit),
844                 _ => Err(head.error("expected boolean literal")),
845             }
846         }
847     }
848 }
849 
850 #[cfg(feature = "printing")]
851 mod printing {
852     use super::*;
853     use proc_macro2::TokenStream;
854     use quote::{ToTokens, TokenStreamExt};
855 
856     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
857     impl ToTokens for LitStr {
to_tokens(&self, tokens: &mut TokenStream)858         fn to_tokens(&self, tokens: &mut TokenStream) {
859             self.repr.token.to_tokens(tokens);
860         }
861     }
862 
863     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
864     impl ToTokens for LitByteStr {
to_tokens(&self, tokens: &mut TokenStream)865         fn to_tokens(&self, tokens: &mut TokenStream) {
866             self.repr.token.to_tokens(tokens);
867         }
868     }
869 
870     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
871     impl ToTokens for LitByte {
to_tokens(&self, tokens: &mut TokenStream)872         fn to_tokens(&self, tokens: &mut TokenStream) {
873             self.repr.token.to_tokens(tokens);
874         }
875     }
876 
877     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
878     impl ToTokens for LitChar {
to_tokens(&self, tokens: &mut TokenStream)879         fn to_tokens(&self, tokens: &mut TokenStream) {
880             self.repr.token.to_tokens(tokens);
881         }
882     }
883 
884     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
885     impl ToTokens for LitInt {
to_tokens(&self, tokens: &mut TokenStream)886         fn to_tokens(&self, tokens: &mut TokenStream) {
887             self.repr.token.to_tokens(tokens);
888         }
889     }
890 
891     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
892     impl ToTokens for LitFloat {
to_tokens(&self, tokens: &mut TokenStream)893         fn to_tokens(&self, tokens: &mut TokenStream) {
894             self.repr.token.to_tokens(tokens);
895         }
896     }
897 
898     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
899     impl ToTokens for LitBool {
to_tokens(&self, tokens: &mut TokenStream)900         fn to_tokens(&self, tokens: &mut TokenStream) {
901             let s = if self.value { "true" } else { "false" };
902             tokens.append(Ident::new(s, self.span));
903         }
904     }
905 }
906 
907 mod value {
908     use super::*;
909     use crate::bigint::BigInt;
910     use proc_macro2::TokenStream;
911     use std::char;
912     use std::ops::{Index, RangeFrom};
913 
914     impl Lit {
915         /// Interpret a Syn literal from a proc-macro2 literal.
new(token: Literal) -> Self916         pub fn new(token: Literal) -> Self {
917             let repr = token.to_string();
918 
919             match byte(&repr, 0) {
920                 b'"' | b'r' => {
921                     let (_, suffix) = parse_lit_str(&repr);
922                     return Lit::Str(LitStr {
923                         repr: Box::new(LitRepr { token, suffix }),
924                     });
925                 }
926                 b'b' => match byte(&repr, 1) {
927                     b'"' | b'r' => {
928                         let (_, suffix) = parse_lit_byte_str(&repr);
929                         return Lit::ByteStr(LitByteStr {
930                             repr: Box::new(LitRepr { token, suffix }),
931                         });
932                     }
933                     b'\'' => {
934                         let (_, suffix) = parse_lit_byte(&repr);
935                         return Lit::Byte(LitByte {
936                             repr: Box::new(LitRepr { token, suffix }),
937                         });
938                     }
939                     _ => {}
940                 },
941                 b'\'' => {
942                     let (_, suffix) = parse_lit_char(&repr);
943                     return Lit::Char(LitChar {
944                         repr: Box::new(LitRepr { token, suffix }),
945                     });
946                 }
947                 b'0'..=b'9' | b'-' => {
948                     if let Some((digits, suffix)) = parse_lit_int(&repr) {
949                         return Lit::Int(LitInt {
950                             repr: Box::new(LitIntRepr {
951                                 token,
952                                 digits,
953                                 suffix,
954                             }),
955                         });
956                     }
957                     if let Some((digits, suffix)) = parse_lit_float(&repr) {
958                         return Lit::Float(LitFloat {
959                             repr: Box::new(LitFloatRepr {
960                                 token,
961                                 digits,
962                                 suffix,
963                             }),
964                         });
965                     }
966                 }
967                 b't' | b'f' => {
968                     if repr == "true" || repr == "false" {
969                         return Lit::Bool(LitBool {
970                             value: repr == "true",
971                             span: token.span(),
972                         });
973                     }
974                 }
975                 _ => {}
976             }
977 
978             panic!("Unrecognized literal: `{}`", repr);
979         }
980 
suffix(&self) -> &str981         pub fn suffix(&self) -> &str {
982             match self {
983                 Lit::Str(lit) => lit.suffix(),
984                 Lit::ByteStr(lit) => lit.suffix(),
985                 Lit::Byte(lit) => lit.suffix(),
986                 Lit::Char(lit) => lit.suffix(),
987                 Lit::Int(lit) => lit.suffix(),
988                 Lit::Float(lit) => lit.suffix(),
989                 Lit::Bool(_) | Lit::Verbatim(_) => "",
990             }
991         }
992 
span(&self) -> Span993         pub fn span(&self) -> Span {
994             match self {
995                 Lit::Str(lit) => lit.span(),
996                 Lit::ByteStr(lit) => lit.span(),
997                 Lit::Byte(lit) => lit.span(),
998                 Lit::Char(lit) => lit.span(),
999                 Lit::Int(lit) => lit.span(),
1000                 Lit::Float(lit) => lit.span(),
1001                 Lit::Bool(lit) => lit.span,
1002                 Lit::Verbatim(lit) => lit.span(),
1003             }
1004         }
1005 
set_span(&mut self, span: Span)1006         pub fn set_span(&mut self, span: Span) {
1007             match self {
1008                 Lit::Str(lit) => lit.set_span(span),
1009                 Lit::ByteStr(lit) => lit.set_span(span),
1010                 Lit::Byte(lit) => lit.set_span(span),
1011                 Lit::Char(lit) => lit.set_span(span),
1012                 Lit::Int(lit) => lit.set_span(span),
1013                 Lit::Float(lit) => lit.set_span(span),
1014                 Lit::Bool(lit) => lit.span = span,
1015                 Lit::Verbatim(lit) => lit.set_span(span),
1016             }
1017         }
1018     }
1019 
1020     /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
1021     /// past the end of the input buffer.
byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u81022     pub fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
1023         let s = s.as_ref();
1024         if idx < s.len() {
1025             s[idx]
1026         } else {
1027             0
1028         }
1029     }
1030 
next_chr(s: &str) -> char1031     fn next_chr(s: &str) -> char {
1032         s.chars().next().unwrap_or('\0')
1033     }
1034 
1035     // Returns (content, suffix).
parse_lit_str(s: &str) -> (Box<str>, Box<str>)1036     pub fn parse_lit_str(s: &str) -> (Box<str>, Box<str>) {
1037         match byte(s, 0) {
1038             b'"' => parse_lit_str_cooked(s),
1039             b'r' => parse_lit_str_raw(s),
1040             _ => unreachable!(),
1041         }
1042     }
1043 
1044     // Clippy false positive
1045     // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
1046     #[allow(clippy::needless_continue)]
parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>)1047     fn parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>) {
1048         assert_eq!(byte(s, 0), b'"');
1049         s = &s[1..];
1050 
1051         let mut content = String::new();
1052         'outer: loop {
1053             let ch = match byte(s, 0) {
1054                 b'"' => break,
1055                 b'\\' => {
1056                     let b = byte(s, 1);
1057                     s = &s[2..];
1058                     match b {
1059                         b'x' => {
1060                             let (byte, rest) = backslash_x(s);
1061                             s = rest;
1062                             assert!(byte <= 0x80, "Invalid \\x byte in string literal");
1063                             char::from_u32(u32::from(byte)).unwrap()
1064                         }
1065                         b'u' => {
1066                             let (chr, rest) = backslash_u(s);
1067                             s = rest;
1068                             chr
1069                         }
1070                         b'n' => '\n',
1071                         b'r' => '\r',
1072                         b't' => '\t',
1073                         b'\\' => '\\',
1074                         b'0' => '\0',
1075                         b'\'' => '\'',
1076                         b'"' => '"',
1077                         b'\r' | b'\n' => loop {
1078                             let ch = next_chr(s);
1079                             if ch.is_whitespace() {
1080                                 s = &s[ch.len_utf8()..];
1081                             } else {
1082                                 continue 'outer;
1083                             }
1084                         },
1085                         b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1086                     }
1087                 }
1088                 b'\r' => {
1089                     assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
1090                     s = &s[2..];
1091                     '\n'
1092                 }
1093                 _ => {
1094                     let ch = next_chr(s);
1095                     s = &s[ch.len_utf8()..];
1096                     ch
1097                 }
1098             };
1099             content.push(ch);
1100         }
1101 
1102         assert!(s.starts_with('"'));
1103         let content = content.into_boxed_str();
1104         let suffix = s[1..].to_owned().into_boxed_str();
1105         (content, suffix)
1106     }
1107 
parse_lit_str_raw(mut s: &str) -> (Box<str>, Box<str>)1108     fn parse_lit_str_raw(mut s: &str) -> (Box<str>, Box<str>) {
1109         assert_eq!(byte(s, 0), b'r');
1110         s = &s[1..];
1111 
1112         let mut pounds = 0;
1113         while byte(s, pounds) == b'#' {
1114             pounds += 1;
1115         }
1116         assert_eq!(byte(s, pounds), b'"');
1117         let close = s.rfind('"').unwrap();
1118         for end in s[close + 1..close + 1 + pounds].bytes() {
1119             assert_eq!(end, b'#');
1120         }
1121 
1122         let content = s[pounds + 1..close].to_owned().into_boxed_str();
1123         let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str();
1124         (content, suffix)
1125     }
1126 
1127     // Returns (content, suffix).
parse_lit_byte_str(s: &str) -> (Vec<u8>, Box<str>)1128     pub fn parse_lit_byte_str(s: &str) -> (Vec<u8>, Box<str>) {
1129         assert_eq!(byte(s, 0), b'b');
1130         match byte(s, 1) {
1131             b'"' => parse_lit_byte_str_cooked(s),
1132             b'r' => parse_lit_byte_str_raw(s),
1133             _ => unreachable!(),
1134         }
1135     }
1136 
1137     // Clippy false positive
1138     // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
1139     #[allow(clippy::needless_continue)]
parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>)1140     fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>) {
1141         assert_eq!(byte(s, 0), b'b');
1142         assert_eq!(byte(s, 1), b'"');
1143         s = &s[2..];
1144 
1145         // We're going to want to have slices which don't respect codepoint boundaries.
1146         let mut v = s.as_bytes();
1147 
1148         let mut out = Vec::new();
1149         'outer: loop {
1150             let byte = match byte(v, 0) {
1151                 b'"' => break,
1152                 b'\\' => {
1153                     let b = byte(v, 1);
1154                     v = &v[2..];
1155                     match b {
1156                         b'x' => {
1157                             let (b, rest) = backslash_x(v);
1158                             v = rest;
1159                             b
1160                         }
1161                         b'n' => b'\n',
1162                         b'r' => b'\r',
1163                         b't' => b'\t',
1164                         b'\\' => b'\\',
1165                         b'0' => b'\0',
1166                         b'\'' => b'\'',
1167                         b'"' => b'"',
1168                         b'\r' | b'\n' => loop {
1169                             let byte = byte(v, 0);
1170                             let ch = char::from_u32(u32::from(byte)).unwrap();
1171                             if ch.is_whitespace() {
1172                                 v = &v[1..];
1173                             } else {
1174                                 continue 'outer;
1175                             }
1176                         },
1177                         b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1178                     }
1179                 }
1180                 b'\r' => {
1181                     assert_eq!(byte(v, 1), b'\n', "Bare CR not allowed in string");
1182                     v = &v[2..];
1183                     b'\n'
1184                 }
1185                 b => {
1186                     v = &v[1..];
1187                     b
1188                 }
1189             };
1190             out.push(byte);
1191         }
1192 
1193         assert_eq!(byte(v, 0), b'"');
1194         let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1195         (out, suffix)
1196     }
1197 
parse_lit_byte_str_raw(s: &str) -> (Vec<u8>, Box<str>)1198     fn parse_lit_byte_str_raw(s: &str) -> (Vec<u8>, Box<str>) {
1199         assert_eq!(byte(s, 0), b'b');
1200         let (value, suffix) = parse_lit_str_raw(&s[1..]);
1201         (String::from(value).into_bytes(), suffix)
1202     }
1203 
1204     // Returns (value, suffix).
parse_lit_byte(s: &str) -> (u8, Box<str>)1205     pub fn parse_lit_byte(s: &str) -> (u8, Box<str>) {
1206         assert_eq!(byte(s, 0), b'b');
1207         assert_eq!(byte(s, 1), b'\'');
1208 
1209         // We're going to want to have slices which don't respect codepoint boundaries.
1210         let mut v = s[2..].as_bytes();
1211 
1212         let b = match byte(v, 0) {
1213             b'\\' => {
1214                 let b = byte(v, 1);
1215                 v = &v[2..];
1216                 match b {
1217                     b'x' => {
1218                         let (b, rest) = backslash_x(v);
1219                         v = rest;
1220                         b
1221                     }
1222                     b'n' => b'\n',
1223                     b'r' => b'\r',
1224                     b't' => b'\t',
1225                     b'\\' => b'\\',
1226                     b'0' => b'\0',
1227                     b'\'' => b'\'',
1228                     b'"' => b'"',
1229                     b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1230                 }
1231             }
1232             b => {
1233                 v = &v[1..];
1234                 b
1235             }
1236         };
1237 
1238         assert_eq!(byte(v, 0), b'\'');
1239         let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1240         (b, suffix)
1241     }
1242 
1243     // Returns (value, suffix).
parse_lit_char(mut s: &str) -> (char, Box<str>)1244     pub fn parse_lit_char(mut s: &str) -> (char, Box<str>) {
1245         assert_eq!(byte(s, 0), b'\'');
1246         s = &s[1..];
1247 
1248         let ch = match byte(s, 0) {
1249             b'\\' => {
1250                 let b = byte(s, 1);
1251                 s = &s[2..];
1252                 match b {
1253                     b'x' => {
1254                         let (byte, rest) = backslash_x(s);
1255                         s = rest;
1256                         assert!(byte <= 0x80, "Invalid \\x byte in string literal");
1257                         char::from_u32(u32::from(byte)).unwrap()
1258                     }
1259                     b'u' => {
1260                         let (chr, rest) = backslash_u(s);
1261                         s = rest;
1262                         chr
1263                     }
1264                     b'n' => '\n',
1265                     b'r' => '\r',
1266                     b't' => '\t',
1267                     b'\\' => '\\',
1268                     b'0' => '\0',
1269                     b'\'' => '\'',
1270                     b'"' => '"',
1271                     b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1272                 }
1273             }
1274             _ => {
1275                 let ch = next_chr(s);
1276                 s = &s[ch.len_utf8()..];
1277                 ch
1278             }
1279         };
1280         assert_eq!(byte(s, 0), b'\'');
1281         let suffix = s[1..].to_owned().into_boxed_str();
1282         (ch, suffix)
1283     }
1284 
backslash_x<S>(s: &S) -> (u8, &S) where S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,1285     fn backslash_x<S>(s: &S) -> (u8, &S)
1286     where
1287         S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
1288     {
1289         let mut ch = 0;
1290         let b0 = byte(s, 0);
1291         let b1 = byte(s, 1);
1292         ch += 0x10
1293             * match b0 {
1294                 b'0'..=b'9' => b0 - b'0',
1295                 b'a'..=b'f' => 10 + (b0 - b'a'),
1296                 b'A'..=b'F' => 10 + (b0 - b'A'),
1297                 _ => panic!("unexpected non-hex character after \\x"),
1298             };
1299         ch += match b1 {
1300             b'0'..=b'9' => b1 - b'0',
1301             b'a'..=b'f' => 10 + (b1 - b'a'),
1302             b'A'..=b'F' => 10 + (b1 - b'A'),
1303             _ => panic!("unexpected non-hex character after \\x"),
1304         };
1305         (ch, &s[2..])
1306     }
1307 
backslash_u(mut s: &str) -> (char, &str)1308     fn backslash_u(mut s: &str) -> (char, &str) {
1309         if byte(s, 0) != b'{' {
1310             panic!("{}", "expected { after \\u");
1311         }
1312         s = &s[1..];
1313 
1314         let mut ch = 0;
1315         let mut digits = 0;
1316         loop {
1317             let b = byte(s, 0);
1318             let digit = match b {
1319                 b'0'..=b'9' => b - b'0',
1320                 b'a'..=b'f' => 10 + b - b'a',
1321                 b'A'..=b'F' => 10 + b - b'A',
1322                 b'_' if digits > 0 => {
1323                     s = &s[1..];
1324                     continue;
1325                 }
1326                 b'}' if digits == 0 => panic!("invalid empty unicode escape"),
1327                 b'}' => break,
1328                 _ => panic!("unexpected non-hex character after \\u"),
1329             };
1330             if digits == 6 {
1331                 panic!("overlong unicode escape (must have at most 6 hex digits)");
1332             }
1333             ch *= 0x10;
1334             ch += u32::from(digit);
1335             digits += 1;
1336             s = &s[1..];
1337         }
1338         assert!(byte(s, 0) == b'}');
1339         s = &s[1..];
1340 
1341         if let Some(ch) = char::from_u32(ch) {
1342             (ch, s)
1343         } else {
1344             panic!("character code {:x} is not a valid unicode character", ch);
1345         }
1346     }
1347 
1348     // Returns base 10 digits and suffix.
parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)>1349     pub fn parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)> {
1350         let negative = byte(s, 0) == b'-';
1351         if negative {
1352             s = &s[1..];
1353         }
1354 
1355         let base = match (byte(s, 0), byte(s, 1)) {
1356             (b'0', b'x') => {
1357                 s = &s[2..];
1358                 16
1359             }
1360             (b'0', b'o') => {
1361                 s = &s[2..];
1362                 8
1363             }
1364             (b'0', b'b') => {
1365                 s = &s[2..];
1366                 2
1367             }
1368             (b'0'..=b'9', _) => 10,
1369             _ => return None,
1370         };
1371 
1372         let mut value = BigInt::new();
1373         'outer: loop {
1374             let b = byte(s, 0);
1375             let digit = match b {
1376                 b'0'..=b'9' => b - b'0',
1377                 b'a'..=b'f' if base > 10 => b - b'a' + 10,
1378                 b'A'..=b'F' if base > 10 => b - b'A' + 10,
1379                 b'_' => {
1380                     s = &s[1..];
1381                     continue;
1382                 }
1383                 // If looking at a floating point literal, we don't want to
1384                 // consider it an integer.
1385                 b'.' if base == 10 => return None,
1386                 b'e' | b'E' if base == 10 => {
1387                     let mut has_exp = false;
1388                     for (i, b) in s[1..].bytes().enumerate() {
1389                         match b {
1390                             b'_' => {}
1391                             b'-' | b'+' => return None,
1392                             b'0'..=b'9' => has_exp = true,
1393                             _ => {
1394                                 let suffix = &s[1 + i..];
1395                                 if has_exp && crate::ident::xid_ok(suffix) {
1396                                     return None;
1397                                 } else {
1398                                     break 'outer;
1399                                 }
1400                             }
1401                         }
1402                     }
1403                     if has_exp {
1404                         return None;
1405                     } else {
1406                         break;
1407                     }
1408                 }
1409                 _ => break,
1410             };
1411 
1412             if digit >= base {
1413                 return None;
1414             }
1415 
1416             value *= base;
1417             value += digit;
1418             s = &s[1..];
1419         }
1420 
1421         let suffix = s;
1422         if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
1423             let mut repr = value.to_string();
1424             if negative {
1425                 repr.insert(0, '-');
1426             }
1427             Some((repr.into_boxed_str(), suffix.to_owned().into_boxed_str()))
1428         } else {
1429             None
1430         }
1431     }
1432 
1433     // Returns base 10 digits and suffix.
parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)>1434     pub fn parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)> {
1435         // Rust's floating point literals are very similar to the ones parsed by
1436         // the standard library, except that rust's literals can contain
1437         // ignorable underscores. Let's remove those underscores.
1438 
1439         let mut bytes = input.to_owned().into_bytes();
1440 
1441         let start = (*bytes.get(0)? == b'-') as usize;
1442         match bytes.get(start)? {
1443             b'0'..=b'9' => {}
1444             _ => return None,
1445         }
1446 
1447         let mut read = start;
1448         let mut write = start;
1449         let mut has_dot = false;
1450         let mut has_e = false;
1451         let mut has_sign = false;
1452         let mut has_exponent = false;
1453         while read < bytes.len() {
1454             match bytes[read] {
1455                 b'_' => {
1456                     // Don't increase write
1457                     read += 1;
1458                     continue;
1459                 }
1460                 b'0'..=b'9' => {
1461                     if has_e {
1462                         has_exponent = true;
1463                     }
1464                     bytes[write] = bytes[read];
1465                 }
1466                 b'.' => {
1467                     if has_e || has_dot {
1468                         return None;
1469                     }
1470                     has_dot = true;
1471                     bytes[write] = b'.';
1472                 }
1473                 b'e' | b'E' => {
1474                     match bytes[read + 1..]
1475                         .iter()
1476                         .find(|b| **b != b'_')
1477                         .unwrap_or(&b'\0')
1478                     {
1479                         b'-' | b'+' | b'0'..=b'9' => {}
1480                         _ => break,
1481                     }
1482                     if has_e {
1483                         if has_exponent {
1484                             break;
1485                         } else {
1486                             return None;
1487                         }
1488                     }
1489                     has_e = true;
1490                     bytes[write] = b'e';
1491                 }
1492                 b'-' | b'+' => {
1493                     if has_sign || has_exponent || !has_e {
1494                         return None;
1495                     }
1496                     has_sign = true;
1497                     if bytes[read] == b'-' {
1498                         bytes[write] = bytes[read];
1499                     } else {
1500                         // Omit '+'
1501                         read += 1;
1502                         continue;
1503                     }
1504                 }
1505                 _ => break,
1506             }
1507             read += 1;
1508             write += 1;
1509         }
1510 
1511         if has_e && !has_exponent {
1512             return None;
1513         }
1514 
1515         let mut digits = String::from_utf8(bytes).unwrap();
1516         let suffix = digits.split_off(read);
1517         digits.truncate(write);
1518         if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
1519             Some((digits.into_boxed_str(), suffix.into_boxed_str()))
1520         } else {
1521             None
1522         }
1523     }
1524 
to_literal(repr: &str, digits: &str, suffix: &str) -> Option<Literal>1525     pub fn to_literal(repr: &str, digits: &str, suffix: &str) -> Option<Literal> {
1526         if repr.starts_with('-') {
1527             let f64_parse_finite = || digits.parse().ok().filter(|x: &f64| x.is_finite());
1528             let f32_parse_finite = || digits.parse().ok().filter(|x: &f32| x.is_finite());
1529             if suffix == "f64" {
1530                 f64_parse_finite().map(Literal::f64_suffixed)
1531             } else if suffix == "f32" {
1532                 f32_parse_finite().map(Literal::f32_suffixed)
1533             } else if suffix == "i64" {
1534                 digits.parse().ok().map(Literal::i64_suffixed)
1535             } else if suffix == "i32" {
1536                 digits.parse().ok().map(Literal::i32_suffixed)
1537             } else if suffix == "i16" {
1538                 digits.parse().ok().map(Literal::i16_suffixed)
1539             } else if suffix == "i8" {
1540                 digits.parse().ok().map(Literal::i8_suffixed)
1541             } else if !suffix.is_empty() {
1542                 None
1543             } else if digits.contains('.') {
1544                 f64_parse_finite().map(Literal::f64_unsuffixed)
1545             } else {
1546                 digits.parse().ok().map(Literal::i64_unsuffixed)
1547             }
1548         } else {
1549             let stream = repr.parse::<TokenStream>().unwrap();
1550             match stream.into_iter().next().unwrap() {
1551                 TokenTree::Literal(l) => Some(l),
1552                 _ => unreachable!(),
1553             }
1554         }
1555     }
1556 }
1557