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