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