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