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