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