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