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