1use crate::error::Error;
10use crate::error::ErrorKind;
11use crate::group::parse_delimiters;
12use crate::group::DoubleQuotes;
13use crate::group::SingleQuotes;
14use crate::private::Marker;
15use crate::private::Sealed;
16use crate::to_tokens::ToTokens;
17use crate::Entry;
18use crate::Parse;
19use crate::ParseStream;
20use crate::Result;
21use crate::Span;
22use crate::TokenStream;
23
24use std::cmp::Ordering;
25use std::collections::HashSet;
26use std::fmt;
27use std::hash;
28use std::result;
29use std::sync::Arc;
30
31#[doc(hidden)]
32pub use concat_idents::concat_idents;
33
34pub trait Token: Parse + fmt::Debug + Sealed {
39 fn span(&self) -> &Span;
41
42 #[doc(hidden)]
43 fn set_span(&mut self, span: Span);
44
45 #[doc(hidden)]
46 fn display() -> String;
47}
48
49impl<T: Token> Parse for Option<T> {
50 fn parse(input: ParseStream) -> Result<Self> {
51 input
52 .try_parse()
53 .map_or_else(|_| Ok(None), |value| Ok(Some(value)))
54 }
55}
56
57impl<T: Token> From<&T> for Span {
58 fn from(value: &T) -> Self {
59 value.span().to_owned()
60 }
61}
62
63pub trait Punct: Token {
68 #[doc(hidden)]
69 fn peek(input: ParseStream<'_>) -> bool;
70}
71
72#[derive(Debug, Clone)]
76pub struct LitStrDoubleQuote {
77 string: String,
78 span: Span,
79}
80
81impl LitStrDoubleQuote {
82 pub const fn string(&self) -> &String {
84 &self.string
85 }
86
87 pub const fn new(string: String, span: Span) -> LitStrDoubleQuote {
89 LitStrDoubleQuote { string, span }
90 }
91}
92
93impl PartialEq for LitStrDoubleQuote {
94 fn eq(&self, other: &Self) -> bool {
95 self.string == other.string
96 }
97}
98
99impl Eq for LitStrDoubleQuote {}
100
101impl PartialOrd for LitStrDoubleQuote {
102 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
103 Some(self.cmp(other))
104 }
105}
106
107impl Ord for LitStrDoubleQuote {
108 fn cmp(&self, other: &Self) -> Ordering {
109 self.string.cmp(&other.string)
110 }
111}
112
113impl hash::Hash for LitStrDoubleQuote {
114 fn hash<H: hash::Hasher>(&self, state: &mut H) {
115 self.string.hash(state);
116 }
117}
118
119impl Parse for LitStrDoubleQuote {
120 fn parse(input: ParseStream<'_>) -> Result<Self> {
121 #[cfg(feature = "scan-strings")]
122 if let Entry::LitStrDoubleQuote(string) = input.current()? {
123 input.next_raw();
124 return Ok(string.clone());
125 }
126
127 let (start, end, _) = parse_delimiters::<DoubleQuotes>(input).map_err(|mut err| {
128 err.group_to_string();
129 err
130 })?;
131 let (start, end) = (start.span(), end.span());
132 let string = input.source.contents[start.end..end.start].to_owned();
133 let span = Span::across(start, end);
134 Ok(LitStrDoubleQuote { string, span })
135 }
136}
137
138impl Sealed for LitStrDoubleQuote {}
139
140impl Token for LitStrDoubleQuote {
141 fn span(&self) -> &Span {
142 &self.span
143 }
144
145 fn set_span(&mut self, span: Span) {
146 self.span = span;
147 }
148
149 fn display() -> String {
150 "a string literal".to_string()
151 }
152}
153
154#[doc(hidden)]
155#[allow(non_snake_case)]
156pub const fn LitStrDoubleQuote(marker: Marker) -> LitStrDoubleQuote {
157 match marker {}
158}
159
160#[derive(Debug, Clone)]
164pub struct LitStrSingleQuote {
165 string: String,
166 span: Span,
167}
168
169impl LitStrSingleQuote {
170 pub const fn string(&self) -> &String {
172 &self.string
173 }
174
175 pub const fn new(string: String, span: Span) -> LitStrSingleQuote {
177 LitStrSingleQuote { string, span }
178 }
179}
180
181impl PartialEq for LitStrSingleQuote {
182 fn eq(&self, other: &Self) -> bool {
183 self.string == other.string
184 }
185}
186
187impl Eq for LitStrSingleQuote {}
188
189impl PartialOrd for LitStrSingleQuote {
190 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
191 Some(self.cmp(other))
192 }
193}
194
195impl Ord for LitStrSingleQuote {
196 fn cmp(&self, other: &Self) -> Ordering {
197 self.string.cmp(&other.string)
198 }
199}
200
201impl hash::Hash for LitStrSingleQuote {
202 fn hash<H: hash::Hasher>(&self, state: &mut H) {
203 self.string.hash(state);
204 }
205}
206
207impl Parse for LitStrSingleQuote {
208 fn parse(input: ParseStream<'_>) -> Result<Self> {
209 #[cfg(feature = "scan-strings")]
210 if let Entry::LitStrSingleQuote(string) = input.current()? {
211 input.next_raw();
212 return Ok(string.clone());
213 }
214
215 let (start, end, _) = parse_delimiters::<SingleQuotes>(input).map_err(|mut err| {
216 err.group_to_string();
217 err
218 })?;
219 let (start, end) = (start.span(), end.span());
220 let string = input.source.contents[start.end..end.start].to_owned();
221 let span = Span::across(start, end);
222 Ok(LitStrSingleQuote { string, span })
223 }
224}
225
226impl Sealed for LitStrSingleQuote {}
227
228impl Token for LitStrSingleQuote {
229 fn span(&self) -> &Span {
230 &self.span
231 }
232
233 fn set_span(&mut self, span: Span) {
234 self.span = span;
235 }
236
237 fn display() -> String {
238 "a string literal".to_string()
239 }
240}
241
242#[doc(hidden)]
243#[allow(non_snake_case)]
244pub const fn LitStrSingleQuote(marker: Marker) -> LitStrSingleQuote {
245 match marker {}
246}
247
248#[derive(Debug, Clone)]
252pub struct LitChar {
253 ch: char,
254 span: Span,
255}
256
257impl LitChar {
258 pub const fn ch(&self) -> char {
260 self.ch
261 }
262
263 pub const fn new(ch: char, span: Span) -> LitChar {
265 LitChar { ch, span }
266 }
267}
268
269impl PartialEq for LitChar {
270 fn eq(&self, other: &Self) -> bool {
271 self.ch == other.ch
272 }
273}
274
275impl Eq for LitChar {}
276
277impl PartialOrd for LitChar {
278 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
279 Some(self.cmp(other))
280 }
281}
282
283impl Ord for LitChar {
284 fn cmp(&self, other: &Self) -> Ordering {
285 self.ch.cmp(&other.ch)
286 }
287}
288
289impl hash::Hash for LitChar {
290 fn hash<H: hash::Hasher>(&self, state: &mut H) {
291 self.ch.hash(state);
292 }
293}
294
295impl Parse for LitChar {
296 fn parse(input: ParseStream<'_>) -> Result<Self> {
297 let string: LitStrSingleQuote = input.parse().map_err(|mut err| {
298 err.string_to_char();
299 err
300 })?;
301 if string.string.len() != 1 {
302 return Err(Error::new(
303 Arc::clone(&input.source),
304 ErrorKind::LongChar(string.span),
305 ));
306 }
307 let ch = string.string.chars().next().unwrap();
308 Ok(LitChar {
309 ch,
310 span: string.span,
311 })
312 }
313}
314
315impl Sealed for LitChar {}
316
317impl Token for LitChar {
318 fn span(&self) -> &Span {
319 &self.span
320 }
321
322 fn set_span(&mut self, span: Span) {
323 self.span = span;
324 }
325
326 fn display() -> String {
327 "a character literal".to_string()
328 }
329}
330
331#[doc(hidden)]
332#[allow(non_snake_case)]
333pub const fn LitChar(marker: Marker) -> LitChar {
334 match marker {}
335}
336
337#[derive(Debug, Clone)]
340pub struct Ident {
341 pub(crate) string: String,
342 pub(crate) span: Span,
343}
344
345impl Ident {
346 pub const fn string(&self) -> &String {
348 &self.string
349 }
350
351 pub const fn new(string: String, span: Span) -> Ident {
354 Ident { string, span }
355 }
356
357 fn parse_simple(input: ParseStream) -> Result<Self> {
358 let token = input.next()?;
359 Self::try_from(token.to_owned()).map_or_else(
360 |_| {
361 Err(Error::new(
362 Arc::clone(&input.source),
363 ErrorKind::UnexpectedToken {
364 expected: HashSet::from_iter(["an identifier".to_string()]),
365 span: token.span().clone(),
366 },
367 ))
368 },
369 Ok,
370 )
371 }
372}
373
374impl PartialEq for Ident {
375 fn eq(&self, other: &Self) -> bool {
376 self.string == other.string
377 }
378}
379
380impl Eq for Ident {}
381
382impl PartialOrd for Ident {
383 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
384 Some(self.cmp(other))
385 }
386}
387
388impl Ord for Ident {
389 fn cmp(&self, other: &Self) -> Ordering {
390 self.string.cmp(&other.string)
391 }
392}
393
394impl hash::Hash for Ident {
395 fn hash<H: hash::Hasher>(&self, state: &mut H) {
396 self.string.hash(state);
397 }
398}
399
400impl TryFrom<Entry> for Ident {
401 type Error = Entry;
402
403 fn try_from(value: Entry) -> result::Result<Self, Self::Error> {
404 if let Entry::Ident(token) = value {
405 Ok(token)
406 } else {
407 Err(value)
408 }
409 }
410}
411
412impl Parse for Ident {
413 fn parse(input: ParseStream) -> Result<Self> {
414 let ident = Self::parse_simple(input)?;
415 if ident.string.chars().next().unwrap().is_ascii_digit() {
416 Err(Error::new(
417 Arc::clone(&input.source),
418 ErrorKind::UnexpectedToken {
419 expected: HashSet::from_iter(["an identifier".to_string()]),
420 span: ident.span().clone(),
421 },
422 ))
423 } else {
424 Ok(ident)
425 }
426 }
427}
428
429impl Sealed for Ident {}
430
431impl Token for Ident {
432 fn span(&self) -> &Span {
433 &self.span
434 }
435
436 fn set_span(&mut self, span: Span) {
437 self.span = span;
438 }
439
440 fn display() -> String {
441 "an identifier".to_string()
442 }
443}
444
445#[doc(hidden)]
446#[allow(non_snake_case)]
447pub const fn Ident(marker: Marker) -> Ident {
448 match marker {}
449}
450
451#[derive(Debug, Clone)]
452pub(crate) struct SingleCharPunct {
453 pub(super) kind: PunctKind,
454 pub(super) spacing: Spacing,
455 pub(super) span: Span,
456}
457
458impl SingleCharPunct {
459 pub(crate) const fn new(kind: PunctKind, spacing: Spacing, span: Span) -> SingleCharPunct {
460 SingleCharPunct {
461 kind,
462 spacing,
463 span,
464 }
465 }
466}
467
468impl PartialEq for SingleCharPunct {
469 fn eq(&self, other: &Self) -> bool {
470 self.kind == other.kind && self.spacing == other.spacing
471 }
472}
473
474impl Eq for SingleCharPunct {}
475
476impl PartialOrd for SingleCharPunct {
477 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
478 Some(self.cmp(other))
479 }
480}
481
482impl Ord for SingleCharPunct {
483 fn cmp(&self, other: &Self) -> Ordering {
484 self.kind
485 .cmp(&other.kind)
486 .then(self.spacing.cmp(&other.spacing))
487 }
488}
489
490impl hash::Hash for SingleCharPunct {
491 fn hash<H: hash::Hasher>(&self, state: &mut H) {
492 self.kind.hash(state);
493 self.spacing.hash(state);
494 }
495}
496
497impl<'a> TryFrom<&'a Entry> for &'a SingleCharPunct {
498 type Error = ();
499
500 fn try_from(value: &'a Entry) -> result::Result<Self, Self::Error> {
501 if let Entry::Punct(token) = value {
502 Ok(token)
503 } else {
504 Err(())
505 }
506 }
507}
508
509#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
510pub(crate) enum Spacing {
511 Alone,
512 Joint,
513}
514
515impl From<Result<char>> for Spacing {
516 fn from(value: Result<char>) -> Self {
517 value.map_or(Spacing::Alone, |c| {
518 if PunctKind::try_from(c).is_ok() {
519 Spacing::Joint
520 } else {
521 Spacing::Alone
522 }
523 })
524 }
525}
526
527#[derive(Debug, Clone)]
533pub struct LitInt {
534 value: u64,
535 span: Span,
536}
537
538impl LitInt {
539 pub const fn value(&self) -> u64 {
541 self.value
542 }
543
544 fn parse_decimal_impl(input: ParseStream) -> Result<Self> {
545 let ident = Ident::parse_simple(input)?;
546 Ok(LitInt {
547 value: ident.string.parse().map_err(|_| Error::empty())?,
548 span: ident.span,
549 })
550 }
551
552 pub fn parse_decimal(input: ParseStream) -> Result<Self> {
557 Self::parse_decimal_impl(input).map_err(|_| {
558 input.unexpected_token(HashSet::from_iter(["an integer literal".to_string()]))
559 })
560 }
561
562 pub const fn new(value: u64, span: Span) -> LitInt {
564 LitInt { value, span }
565 }
566
567 fn parse_impl(input: ParseStream) -> Result<Self> {
568 let ident = Ident::parse_simple(input)?;
569 let mut chars = ident.string().chars();
570 let start: u8 = chars
571 .next()
572 .unwrap()
573 .to_string()
574 .parse()
575 .map_err(|_| Error::empty())?;
576 if start == 0 && ident.string.len() >= 3 {
577 let ch = chars.next().unwrap();
578 let result = match ch {
579 'b' | 'B' => Some(u64::from_str_radix(&ident.string[2..], 2)),
580 'o' | 'O' => Some(u64::from_str_radix(&ident.string[2..], 8)),
581 'x' | 'X' => Some(u64::from_str_radix(&ident.string[2..], 16)),
582 _ => None,
583 };
584 if let Some(result) = result {
585 return Ok(LitInt {
586 value: result.map_err(|_| Error::empty())?,
587 span: ident.span,
588 });
589 }
590 }
591
592 Ok(LitInt {
593 value: ident.string.parse().map_err(|_| Error::empty())?,
594 span: ident.span,
595 })
596 }
597}
598
599impl PartialEq for LitInt {
600 fn eq(&self, other: &Self) -> bool {
601 self.value == other.value
602 }
603}
604
605impl Eq for LitInt {}
606
607impl PartialOrd for LitInt {
608 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
609 Some(self.cmp(other))
610 }
611}
612
613impl Ord for LitInt {
614 fn cmp(&self, other: &Self) -> Ordering {
615 self.value.cmp(&other.value)
616 }
617}
618
619impl hash::Hash for LitInt {
620 fn hash<H: hash::Hasher>(&self, state: &mut H) {
621 self.value.hash(state);
622 }
623}
624
625impl Parse for LitInt {
626 fn parse(input: ParseStream) -> Result<Self> {
627 Self::parse_impl(input).map_or_else(
628 |_| Err(input.unexpected_token(HashSet::from_iter(["an integer literal".to_string()]))),
629 Ok,
630 )
631 }
632}
633
634impl Sealed for LitInt {}
635
636impl Token for LitInt {
637 fn span(&self) -> &Span {
638 &self.span
639 }
640
641 fn set_span(&mut self, span: Span) {
642 self.span = span;
643 }
644
645 fn display() -> String {
646 "an integer".to_string()
647 }
648}
649
650#[allow(clippy::cast_precision_loss)] fn int_to_decimal(int: u64) -> f64 {
652 let mut value = int as f64;
653 while value >= 1.0 {
654 value /= 10.0;
655 }
656 value
657}
658
659#[doc(hidden)]
660#[allow(non_snake_case)]
661pub const fn LitInt(marker: Marker) -> LitInt {
662 match marker {}
663}
664
665#[derive(Debug, Clone)]
668pub struct LitFloat {
669 value: f64,
670 span: Span,
671}
672
673impl LitFloat {
674 pub const fn value(&self) -> f64 {
676 self.value
677 }
678
679 pub const fn new(value: f64, span: Span) -> LitFloat {
681 LitFloat { value, span }
682 }
683
684 #[allow(clippy::cast_precision_loss)] fn parse_impl(input: ParseStream) -> Result<Self> {
686 let start = LitInt::parse_decimal(input)?;
687 let _: Dot = input.parse()?;
688 let end = LitInt::parse_decimal(input)?;
689 Ok(LitFloat {
690 value: start.value as f64 + int_to_decimal(end.value),
691 span: Span::new(start.span.start, end.span.end, Arc::clone(&input.source)),
692 })
693 }
694}
695
696impl PartialEq for LitFloat {
697 fn eq(&self, other: &Self) -> bool {
698 self.value == other.value
699 }
700}
701
702impl PartialOrd for LitFloat {
703 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
704 self.value.partial_cmp(&other.value)
705 }
706}
707
708impl Parse for LitFloat {
709 fn parse(input: ParseStream<'_>) -> Result<Self> {
710 Self::parse_impl(input).map_or_else(
711 |_| Err(input.unexpected_token(HashSet::from_iter(["a float literal".to_string()]))),
712 Ok,
713 )
714 }
715}
716
717impl Sealed for LitFloat {}
718
719impl Token for LitFloat {
720 fn span(&self) -> &Span {
721 &self.span
722 }
723
724 fn set_span(&mut self, span: Span) {
725 self.span = span;
726 }
727
728 fn display() -> String {
729 "a floating point literal".to_string()
730 }
731}
732
733#[doc(hidden)]
734#[allow(non_snake_case)]
735pub const fn LitFloat(marker: Marker) -> LitFloat {
736 match marker {}
737}
738
739macro_rules! tokens {
740 {
741 {
742 $( ($t1:ident, $name1:literal) )+
743 }
744 {
745 $( ($t2:ident, $t21:ident, $t22:ident, $name2:literal) )+
746 }
747 {
748 $( ($t3:ident, $t31:ident, $t32:ident, $t33:ident, $name3:literal) )+
749 }
750 } => {
751 $(
752 #[derive(Debug, Clone)]
753 #[doc = concat!("`` ", $name1, " ``")]
754 pub struct $t1 {
755 pub span: Span,
757 }
758
759 impl $t1 {
760 #[doc = concat!("Constructs a new `", stringify!($t1), "` with the given span.")]
761 pub const fn new(span: Span) -> $t1 {
762 $t1 { span }
763 }
764 }
765
766 impl Parse for $t1 {
767 fn parse(input: ParseStream) -> Result<Self> {
768 let token = input.next()?.to_owned();
769 if let Entry::Punct(SingleCharPunct { kind: PunctKind::$t1, span, .. }) = token {
770 Ok(Self { span })
771 } else {
772 Err(Error::new(Arc::clone(&input.source), ErrorKind::UnexpectedToken {
773 expected: HashSet::from_iter(vec![format!("'{}'", $name1)]),
774 span: token.span().clone(),
775 }))
776 }
777 }
778 }
779
780 impl Sealed for $t1 {}
781
782 impl Token for $t1 {
783 fn span(&self) -> &Span {
784 &self.span
785 }
786
787 fn set_span(&mut self, span: Span) {
788 self.span = span;
789 }
790
791 fn display() -> String {
792 $name1.to_string()
793 }
794 }
795
796 impl fmt::Display for $t1 {
797 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
798 write!(f, "{}", $name1)
799 }
800 }
801
802 impl Punct for $t1 {
803 fn peek(input: ParseStream<'_>) -> bool {
804 input.peek($t1)
805 }
806 }
807
808 impl PartialEq for $t1 {
809 fn eq(&self, _other: &Self) -> bool {
810 true
811 }
812 }
813
814 impl Eq for $t1 {}
815
816 impl PartialOrd for $t1 {
817 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
818 Some(self.cmp(other))
819 }
820 }
821
822 impl Ord for $t1 {
823 fn cmp(&self, _: &Self) -> Ordering {
824 Ordering::Equal
825 }
826 }
827
828 impl hash::Hash for $t1 {
829 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
830 }
831
832 impl ToTokens for $t1 {
833 fn to_tokens(&self, tokens: &mut TokenStream) {
834 tokens.push(Entry::Punct(SingleCharPunct::new(
835 PunctKind::$t1,
836 Spacing::Alone,
837 self.span.clone(),
838 )));
839 }
840 }
841
842 #[cfg(feature = "quote")]
843 impl quote::ToTokens for $t1 {
844 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
845 use quote::TokenStreamExt as _;
846 tokens.append_all(proc_macro2::TokenStream::try_from(ToTokens::to_token_stream(self)).unwrap());
847 }
848
849 fn to_token_stream(&self) -> proc_macro2::TokenStream {
850 ToTokens::to_token_stream(self).try_into().unwrap()
851 }
852
853 fn into_token_stream(self) -> proc_macro2::TokenStream {
854 ToTokens::into_token_stream(self).try_into().unwrap()
855 }
856 }
857
858 #[doc(hidden)]
859 #[allow(non_snake_case)]
860 pub const fn $t1(marker: Marker) -> $t1 {
861 match marker {}
862 }
863 )+
864
865 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
866 pub(crate) enum PunctKind {
867 $( $t1 ),+
868 }
869
870 impl TryFrom<char> for PunctKind {
871 type Error = char;
872
873 fn try_from(value: char) -> result::Result<Self, Self::Error> {
874 match value {
875 $( $name1 => Ok(PunctKind::$t1), )+
876 _ => Err(value),
877 }
878 }
879 }
880
881 impl From<PunctKind> for char {
882 fn from(value: PunctKind) -> char {
883 match value {
884 $( PunctKind::$t1 => $name1, )+
885 }
886 }
887 }
888
889 $(
890 #[derive(Debug, Clone)]
891 #[doc = concat!("`", $name2, "`")]
892 pub struct $t2 {
893 pub span: Span,
895 }
896
897 impl $t2 {
898 #[doc = concat!("Constructs a new `", stringify!($t2), "` with the given span.")]
899 pub const fn new(span: Span) -> $t2 {
900 $t2 { span }
901 }
902
903 fn from_tokens_impl(input: ParseStream) -> Result<Self> {
904 if let Entry::Punct(SingleCharPunct { spacing: Spacing::Joint, .. }) = input.current()? {
905
906 } else {
907 return Err(Error::empty());
908 }
909
910 let start: $t21 = input.parse()?;
911 let end: $t22 = input.parse()?;
912 Ok(Self {
913 span: Span::new(start.span.start, end.span.end, start.span.source)
914 })
915 }
916 }
917
918 impl Parse for $t2 {
919 fn parse(input: ParseStream) -> Result<Self> {
920 let span = input.current()?.span();
921 Self::from_tokens_impl(input).map_err(|_| {
922 Error::new(Arc::clone(&input.source), ErrorKind::UnexpectedToken {
923 expected: HashSet::from_iter(vec![format!("'{}'", $name2)]),
924 span: span.clone(),
925 })
926 })
927 }
928 }
929
930 impl Sealed for $t2 {}
931
932 impl Token for $t2 {
933 fn span(&self) -> &Span {
934 &self.span
935 }
936
937 fn set_span(&mut self, span: Span) {
938 self.span = span;
939 }
940
941 fn display() -> String {
942 $name2.to_string()
943 }
944 }
945
946 impl fmt::Display for $t2 {
947 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
948 write!(f, $name2)
949 }
950 }
951
952 impl Punct for $t2 {
953 fn peek(input: ParseStream<'_>) -> bool {
954 input.peek($t2)
955 }
956 }
957
958 impl PartialEq for $t2 {
959 fn eq(&self, _other: &Self) -> bool {
960 true
961 }
962 }
963
964 impl Eq for $t2 {}
965
966 impl PartialOrd for $t2 {
967 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
968 Some(self.cmp(other))
969 }
970 }
971
972 impl Ord for $t2 {
973 fn cmp(&self, _: &Self) -> Ordering {
974 Ordering::Equal
975 }
976 }
977
978 impl hash::Hash for $t2 {
979 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
980 }
981
982 impl ToTokens for $t2 {
983 fn to_tokens(&self, tokens: &mut TokenStream) {
984 let start_span = Span::new(
985 self.span.start,
986 self.span.start + 1,
987 Arc::clone(&self.span.source),
988 );
989 tokens.push(Entry::Punct(SingleCharPunct::new(
990 PunctKind::$t21,
991 Spacing::Joint,
992 start_span,
993 )));
994
995 let end_span = Span::new(
996 self.span.end - 1,
997 self.span.end,
998 Arc::clone(&self.span.source),
999 );
1000 tokens.push(Entry::Punct(SingleCharPunct::new(
1001 PunctKind::$t22,
1002 Spacing::Alone,
1003 end_span,
1004 )));
1005 }
1006 }
1007
1008 #[cfg(feature = "quote")]
1009 impl quote::ToTokens for $t2 {
1010 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1011 use quote::TokenStreamExt as _;
1012 tokens.append_all(proc_macro2::TokenStream::try_from(ToTokens::to_token_stream(self)).unwrap());
1013 }
1014
1015 fn to_token_stream(&self) -> proc_macro2::TokenStream {
1016 ToTokens::to_token_stream(self).try_into().unwrap()
1017 }
1018
1019 fn into_token_stream(self) -> proc_macro2::TokenStream {
1020 ToTokens::into_token_stream(self).try_into().unwrap()
1021 }
1022 }
1023
1024 #[doc(hidden)]
1025 #[allow(non_snake_case)]
1026 pub const fn $t2(marker: Marker) -> $t2 {
1027 match marker {}
1028 }
1029 )+
1030
1031 $(
1032 #[derive(Debug, Clone)]
1033 #[doc = concat!("`", $name3, "`")]
1034 pub struct $t3 {
1035 pub span: Span,
1037 }
1038
1039 impl $t3 {
1040 #[doc = concat!("Constructs a new `", stringify!($t3), "` with the given span.")]
1041 pub const fn new(span: Span) -> $t3 {
1042 $t3 { span }
1043 }
1044
1045 fn from_tokens_impl(input: ParseStream) -> Result<Self> {
1046 if let Entry::Punct(SingleCharPunct { spacing: Spacing::Joint, .. }) = input.current()? {
1047
1048 } else {
1049 return Err(Error::empty());
1050 }
1051 let p1: $t31 = input.parse()?;
1052 if let Entry::Punct(SingleCharPunct { spacing: Spacing::Joint, .. }) = input.current()? {
1053
1054 } else {
1055 return Err(Error::empty());
1056 }
1057 let _p2: $t32 = input.parse()?;
1058 let p3: $t33 = input.parse()?;
1059 Ok(Self {
1060 span: Span::new(p1.span.start, p3.span.end, p1.span.source)
1061 })
1062 }
1063 }
1064
1065 impl Parse for $t3 {
1066 fn parse(input: ParseStream) -> Result<Self> {
1067 let span = input.current()?.span();
1068 Self::from_tokens_impl(input).map_err(|_| {
1069 Error::new(Arc::clone(&input.source), ErrorKind::UnexpectedToken {
1070 expected: HashSet::from_iter(vec![format!("'{}'", $name3)]),
1071 span: span.clone(),
1072 })
1073 })
1074 }
1075 }
1076
1077 impl Sealed for $t3 {}
1078
1079 impl Token for $t3 {
1080 fn span(&self) -> &Span {
1081 &self.span
1082 }
1083
1084 fn set_span(&mut self, span: Span) {
1085 self.span = span;
1086 }
1087
1088 fn display() -> String {
1089 $name3.to_string()
1090 }
1091 }
1092
1093 impl fmt::Display for $t3 {
1094 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1095 write!(f, $name3)
1096 }
1097 }
1098
1099 impl Punct for $t3 {
1100 fn peek(input: ParseStream<'_>) -> bool {
1101 input.peek($t3)
1102 }
1103 }
1104
1105 impl PartialEq for $t3 {
1106 fn eq(&self, _other: &Self) -> bool {
1107 true
1108 }
1109 }
1110
1111 impl Eq for $t3 {}
1112
1113 impl PartialOrd for $t3 {
1114 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1115 Some(self.cmp(other))
1116 }
1117 }
1118
1119 impl Ord for $t3 {
1120 fn cmp(&self, _: &Self) -> Ordering {
1121 Ordering::Equal
1122 }
1123 }
1124
1125 impl hash::Hash for $t3 {
1126 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
1127 }
1128
1129 impl ToTokens for $t3 {
1130 fn to_tokens(&self, tokens: &mut TokenStream) {
1131 let start_span = Span::new(
1132 self.span.start,
1133 self.span.start + 1,
1134 Arc::clone(&self.span.source),
1135 );
1136 tokens.push(Entry::Punct(SingleCharPunct::new(
1137 PunctKind::$t31,
1138 Spacing::Joint,
1139 start_span,
1140 )));
1141
1142 let mid_span = Span::new(
1143 self.span.start + 1,
1144 self.span.start + 2,
1145 Arc::clone(&self.span.source),
1146 );
1147 tokens.push(Entry::Punct(SingleCharPunct::new(
1148 PunctKind::$t32,
1149 Spacing::Joint,
1150 mid_span,
1151 )));
1152
1153 let end_span = Span::new(
1154 self.span.end - 1,
1155 self.span.end,
1156 Arc::clone(&self.span.source),
1157 );
1158 tokens.push(Entry::Punct(SingleCharPunct::new(
1159 PunctKind::$t33,
1160 Spacing::Alone,
1161 end_span,
1162 )));
1163 }
1164 }
1165
1166 #[cfg(feature = "quote")]
1167 impl quote::ToTokens for $t3 {
1168 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1169 use quote::TokenStreamExt as _;
1170 tokens.append_all(proc_macro2::TokenStream::try_from(ToTokens::to_token_stream(self)).unwrap());
1171 }
1172
1173 fn to_token_stream(&self) -> proc_macro2::TokenStream {
1174 ToTokens::to_token_stream(self).try_into().unwrap()
1175 }
1176
1177 fn into_token_stream(self) -> proc_macro2::TokenStream {
1178 ToTokens::into_token_stream(self).try_into().unwrap()
1179 }
1180 }
1181
1182 #[doc(hidden)]
1183 #[allow(non_snake_case)]
1184 pub const fn $t3(marker: Marker) -> $t3 {
1185 match marker {}
1186 }
1187 )+
1188 };
1189}
1190
1191tokens! {
1192 {
1193 (Bang, '!')
1194 (Colon, ':')
1195 (Equal, '=')
1196 (SemiColon, ';')
1197 (LAngle, '<')
1198 (RAngle, '>')
1199 (Plus, '+')
1200 (Dash, '-')
1201 (Asterisk, '*')
1202 (Slash, '/')
1203 (Percent, '%')
1204 (Dot, '.')
1205 (Comma, ',')
1206 (LeftParen, '(')
1207 (RightParen, ')')
1208 (LeftBracket, '[')
1209 (RightBracket, ']')
1210 (LeftBrace, '{')
1211 (RightBrace, '}')
1212 (At, '@')
1213 (Caret, '^')
1214 (BackTick, '`')
1215 (Pipe, '|')
1216 (Ampersand, '&')
1217 (Tilde, '~')
1218 (Tilde2, '¬')
1219 (Backslash, '\\')
1220 (Question, '?')
1221 (Hash, '#')
1222 (Pound, '£')
1223 (Dollar, '$')
1224 (UnderScore, '_')
1225 (SingleQuote, '\'')
1226 (DoubleQuote, '"')
1227 }
1228 {
1229 (BangEqual, Bang, Equal, "!=")
1230 (EqualEqual, Equal, Equal, "==")
1231 (RAngleEqual, RAngle, Equal, ">=")
1232 (LAngleEqual, LAngle, Equal, "<=")
1233 (PlusEqual, Plus, Equal, "+=")
1234 (DashEqual, Dash, Equal, "-=")
1235 (AsteriskEqual, Asterisk, Equal, "*=")
1236 (SlashEqual, Slash, Equal, "/=")
1237 (PercentEqual, Percent, Equal, "%=")
1238 (LAngleLAngle, LAngle, LAngle, "<<")
1239 (RAngleRAngle, RAngle, RAngle, ">>")
1240 (LThinArrow, LAngle, Dash, "<-")
1241 (RThinArrow, Dash, RAngle, "->")
1242 (FatArrow, Equal, RAngle, "=>")
1243 (SlashSlash, Slash, Slash, "//")
1244 (ColonColon, Colon, Colon, "::")
1245 (HashHash, Hash, Hash, "##")
1246 (AmpersandAmpersand, Ampersand, Ampersand, "&&")
1247 (PipePipe, Pipe, Pipe, "||")
1248 (PlusPlus, Plus, Plus, "++")
1249 (DashDash, Dash, Dash, "--")
1250 }
1251 {
1252 (HashHashHash, Hash, Hash, Hash, "###")
1253 (SlashSlashEqual, Slash, Slash, Equal, "//=")
1254 (LAngleLAngleEqual, LAngle, LAngle, Equal, "<<=")
1255 (RAngleRAngleEqual, RAngle, RAngle, Equal, ">>=")
1256 (ColonColonEqual, Colon, Colon, Equal, "::=")
1257 }
1258}
1259
1260trait JoinedPunct: Sized + fmt::Debug {
1261 fn display() -> String;
1262
1263 fn parse(input: ParseStream) -> Result<Self>;
1264}
1265
1266impl<T1: JoinedPunct, T2: JoinedPunct> JoinedPunct for (T1, T2) {
1267 fn display() -> String {
1268 T1::display() + &T2::display()
1269 }
1270
1271 fn parse(input: ParseStream) -> Result<Self> {
1272 Ok((T1::parse(input)?, T2::parse(input)?))
1273 }
1274}
1275
1276impl<T: Punct> JoinedPunct for (T,) {
1277 fn display() -> String {
1278 T::display()
1279 }
1280
1281 fn parse(input: ParseStream) -> Result<Self> {
1282 T::parse(input).map(|value| (value,))
1283 }
1284}
1285
1286impl<T: JoinedPunct> Parse for (T, Span) {
1287 fn parse(input: ParseStream) -> Result<Self> {
1288 let span = input.current()?.span();
1289 let value = T::parse(input).map_err(|_| {
1290 Error::new(
1291 Arc::clone(&input.source),
1292 ErrorKind::UnexpectedToken {
1293 expected: HashSet::from_iter(vec![T::display()]),
1294 span: span.clone(),
1295 },
1296 )
1297 })?;
1298 let span = Span::new(
1299 span.start,
1300 input.get_relative(-1)?.span().end,
1301 Arc::clone(&input.source),
1302 );
1303 Ok((value, span))
1304 }
1305}
1306
1307impl<T: JoinedPunct> Sealed for (T, Span) {}
1308
1309#[doc(hidden)]
1310impl<T: JoinedPunct> Token for (T, Span) {
1311 fn span(&self) -> &Span {
1312 &self.1
1313 }
1314
1315 fn set_span(&mut self, span: Span) {
1316 self.1 = span;
1317 }
1318
1319 fn display() -> String {
1320 T::display()
1321 }
1322}
1323
1324impl<T: JoinedPunct> Punct for (T, Span) {
1325 fn peek(input: ParseStream) -> bool {
1326 input.parse_undo::<(T, Span)>().is_ok()
1327 }
1328}
1329
1330#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1331pub(crate) enum WhiteSpace {
1332 Space2(Space2),
1333 Tab(Tab),
1334 NewLine(NewLine),
1335 CarriageReturn(CarriageReturn),
1336}
1337
1338impl WhiteSpace {
1339 pub(crate) const fn span(&self) -> &Span {
1340 match self {
1341 WhiteSpace::Space2(Space2 { span })
1342 | WhiteSpace::Tab(Tab { span })
1343 | WhiteSpace::NewLine(NewLine { span })
1344 | WhiteSpace::CarriageReturn(CarriageReturn { span }) => span,
1345 }
1346 }
1347
1348 #[cfg(feature = "proc-macro2")]
1349 pub(crate) fn set_span(&mut self, span: Span) {
1350 match self {
1351 WhiteSpace::Space2(Space2 {
1352 span: original_span,
1353 })
1354 | WhiteSpace::Tab(Tab {
1355 span: original_span,
1356 })
1357 | WhiteSpace::NewLine(NewLine {
1358 span: original_span,
1359 })
1360 | WhiteSpace::CarriageReturn(CarriageReturn {
1361 span: original_span,
1362 }) => *original_span = span,
1363 }
1364 }
1365
1366 pub(crate) fn display(&self) -> String {
1367 match self {
1368 WhiteSpace::Space2(_) => Space2::display(),
1369 WhiteSpace::Tab(_) => Tab::display(),
1370 WhiteSpace::NewLine(_) => NewLine::display(),
1371 WhiteSpace::CarriageReturn(_) => CarriageReturn::display(),
1372 }
1373 }
1374}
1375
1376#[derive(Debug, Clone)]
1378pub struct Space2 {
1379 pub span: Span,
1381}
1382
1383impl Parse for Space2 {
1384 fn parse(input: ParseStream) -> Result<Self> {
1385 let token = input.next()?;
1386 if let Entry::WhiteSpace(WhiteSpace::Space2(value)) = token {
1387 Ok(value.clone())
1388 } else {
1389 Err(input.unexpected_token(HashSet::from_iter(["a two-space tab".to_string()])))
1390 }
1391 }
1392}
1393
1394impl Sealed for Space2 {}
1395
1396impl Token for Space2 {
1397 fn span(&self) -> &Span {
1398 &self.span
1399 }
1400
1401 fn set_span(&mut self, span: Span) {
1402 self.span = span;
1403 }
1404
1405 fn display() -> String {
1406 " ".to_string()
1407 }
1408}
1409
1410impl PartialEq for Space2 {
1411 fn eq(&self, _other: &Self) -> bool {
1412 true
1413 }
1414}
1415
1416impl Eq for Space2 {}
1417
1418impl PartialOrd for Space2 {
1419 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1420 Some(self.cmp(other))
1421 }
1422}
1423
1424impl Ord for Space2 {
1425 fn cmp(&self, _: &Self) -> Ordering {
1426 Ordering::Equal
1427 }
1428}
1429
1430impl hash::Hash for Space2 {
1431 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
1432}
1433
1434#[doc(hidden)]
1435#[allow(non_snake_case)]
1436pub const fn Space2(marker: Marker) -> Space2 {
1437 match marker {}
1438}
1439
1440#[derive(Debug, Clone)]
1442pub struct Space4 {
1443 pub span: Span,
1445}
1446
1447impl Space4 {
1448 fn parse_impl(input: ParseStream) -> Result<Self> {
1449 let start: Space2 = input.parse()?;
1450 let end: Space2 = input.parse()?;
1451 if start.span.end != end.span.start {
1452 return Err(Error::empty());
1453 }
1454 Ok(Space4 {
1455 span: Span::across(start.span(), end.span()),
1456 })
1457 }
1458}
1459
1460impl Parse for Space4 {
1461 fn parse(input: ParseStream) -> Result<Self> {
1462 Self::parse_impl(input).map_err(|_| {
1463 input.unexpected_token(HashSet::from_iter(["a four-space tab".to_string()]))
1464 })
1465 }
1466}
1467
1468impl Sealed for Space4 {}
1469
1470impl Token for Space4 {
1471 fn span(&self) -> &Span {
1472 &self.span
1473 }
1474
1475 fn set_span(&mut self, span: Span) {
1476 self.span = span;
1477 }
1478
1479 fn display() -> String {
1480 " ".to_string()
1481 }
1482}
1483
1484impl PartialEq for Space4 {
1485 fn eq(&self, _other: &Self) -> bool {
1486 true
1487 }
1488}
1489
1490impl Eq for Space4 {}
1491
1492impl PartialOrd for Space4 {
1493 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1494 Some(self.cmp(other))
1495 }
1496}
1497
1498impl Ord for Space4 {
1499 fn cmp(&self, _: &Self) -> Ordering {
1500 Ordering::Equal
1501 }
1502}
1503
1504impl hash::Hash for Space4 {
1505 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
1506}
1507
1508#[doc(hidden)]
1509#[allow(non_snake_case)]
1510pub const fn Space4(marker: Marker) -> Space4 {
1511 match marker {}
1512}
1513
1514#[derive(Debug, Clone)]
1516pub struct Tab {
1517 pub span: Span,
1519}
1520
1521impl Parse for Tab {
1522 fn parse(input: ParseStream) -> Result<Self> {
1523 if let Entry::WhiteSpace(WhiteSpace::Tab(value)) = input.next()? {
1524 Ok(value.clone())
1525 } else {
1526 Err(input.unexpected_token(HashSet::from_iter(["a tab".to_string()])))
1527 }
1528 }
1529}
1530
1531impl Sealed for Tab {}
1532
1533impl Token for Tab {
1534 fn span(&self) -> &Span {
1535 &self.span
1536 }
1537
1538 fn set_span(&mut self, span: Span) {
1539 self.span = span;
1540 }
1541
1542 fn display() -> String {
1543 "\t".to_string()
1544 }
1545}
1546
1547impl PartialEq for Tab {
1548 fn eq(&self, _other: &Self) -> bool {
1549 true
1550 }
1551}
1552
1553impl Eq for Tab {}
1554
1555impl PartialOrd for Tab {
1556 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1557 Some(self.cmp(other))
1558 }
1559}
1560
1561impl Ord for Tab {
1562 fn cmp(&self, _: &Self) -> Ordering {
1563 Ordering::Equal
1564 }
1565}
1566
1567impl hash::Hash for Tab {
1568 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
1569}
1570
1571#[doc(hidden)]
1572#[allow(non_snake_case)]
1573pub const fn Tab(marker: Marker) -> Tab {
1574 match marker {}
1575}
1576
1577#[derive(Debug, Clone)]
1579pub struct NewLine {
1580 pub span: Span,
1582}
1583
1584impl Parse for NewLine {
1585 fn parse(input: ParseStream) -> Result<Self> {
1586 if let Entry::WhiteSpace(WhiteSpace::NewLine(value)) = input.next()? {
1587 Ok(value.clone())
1588 } else {
1589 Err(input.unexpected_token(HashSet::from_iter(["\\n".to_string()])))
1590 }
1591 }
1592}
1593
1594impl Sealed for NewLine {}
1595
1596impl Token for NewLine {
1597 fn span(&self) -> &Span {
1598 &self.span
1599 }
1600
1601 fn set_span(&mut self, span: Span) {
1602 self.span = span;
1603 }
1604
1605 fn display() -> String {
1606 "\\n".to_string()
1607 }
1608}
1609
1610impl PartialEq for NewLine {
1611 fn eq(&self, _other: &Self) -> bool {
1612 true
1613 }
1614}
1615
1616impl Eq for NewLine {}
1617
1618impl PartialOrd for NewLine {
1619 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1620 Some(self.cmp(other))
1621 }
1622}
1623
1624impl Ord for NewLine {
1625 fn cmp(&self, _: &Self) -> Ordering {
1626 Ordering::Equal
1627 }
1628}
1629
1630impl hash::Hash for NewLine {
1631 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
1632}
1633
1634#[doc(hidden)]
1635#[allow(non_snake_case)]
1636pub const fn NewLine(marker: Marker) -> NewLine {
1637 match marker {}
1638}
1639
1640#[derive(Debug, Clone)]
1642pub struct CarriageReturn {
1643 pub span: Span,
1645}
1646
1647impl Parse for CarriageReturn {
1648 fn parse(input: ParseStream) -> Result<Self> {
1649 if let Entry::WhiteSpace(WhiteSpace::CarriageReturn(value)) = input.next()? {
1650 Ok(value.clone())
1651 } else {
1652 Err(input.unexpected_token(HashSet::from_iter(["a carriage return".to_string()])))
1653 }
1654 }
1655}
1656
1657impl Sealed for CarriageReturn {}
1658
1659impl Token for CarriageReturn {
1660 fn span(&self) -> &Span {
1661 &self.span
1662 }
1663
1664 fn set_span(&mut self, span: Span) {
1665 self.span = span;
1666 }
1667
1668 fn display() -> String {
1669 "a carriage return".to_string()
1670 }
1671}
1672
1673impl PartialEq for CarriageReturn {
1674 fn eq(&self, _other: &Self) -> bool {
1675 true
1676 }
1677}
1678
1679impl Eq for CarriageReturn {}
1680
1681impl PartialOrd for CarriageReturn {
1682 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1683 Some(self.cmp(other))
1684 }
1685}
1686
1687impl Ord for CarriageReturn {
1688 fn cmp(&self, _: &Self) -> Ordering {
1689 Ordering::Equal
1690 }
1691}
1692
1693impl hash::Hash for CarriageReturn {
1694 fn hash<H: hash::Hasher>(&self, _: &mut H) {}
1695}
1696
1697#[doc(hidden)]
1698#[allow(non_snake_case)]
1699pub const fn CarriageReturn(marker: Marker) -> CarriageReturn {
1700 match marker {}
1701}
1702
1703#[macro_export]
1719macro_rules! keywords {
1720 [ $( $kw:ident $(as $name:ident)? ),+ $(,)? ] => {
1721 $(
1722 $crate::keywords!(@ $kw $(as $name)?);
1723 )+
1724
1725 #[allow(dead_code)]
1727 pub fn ident(input: $crate::ParseStream) -> $crate::Result<$crate::token::Ident> {
1728 let ident: $crate::token::Ident = input.parse()?;
1729 if [$( ::core::stringify!($kw) ),+].contains(&ident.string().as_str()) {
1730 $crate::Result::Err(input.unexpected_token(
1731 ::std::collections::HashSet::from_iter(["an identifier".to_string()]),
1732 ))
1733 } else {
1734 $crate::Result::Ok(ident)
1735 }
1736 }
1737 };
1738 (@ $kw:ident) => {
1739 $crate::keywords!(@ $kw as $kw);
1740 };
1741 (@ $kw:ident as $name:ident) => {
1742 #[derive(Debug, Clone)]
1743 #[allow(non_camel_case_types)]
1744 pub struct $name {
1745 ident: $crate::token::Ident
1746 }
1747
1748 impl $name {
1749 #[allow(dead_code)]
1750 pub fn new(input: $crate::ParseStream) -> Self {
1751 Self {
1752 ident: $crate::token::Ident::new(::core::stringify!($kw).to_string(), input.empty_span()),
1753 }
1754 }
1755
1756 #[allow(dead_code)]
1757 pub const fn ident(&self) -> &$crate::token::Ident {
1758 &self.ident
1759 }
1760 }
1761
1762 impl $crate::Parse for $name {
1763 fn parse(input: $crate::ParseStream) -> $crate::Result<Self> {
1764 let ident: $crate::token::Ident = $crate::Parse::parse(input)?;
1765 if ident.string() == ::core::stringify!($kw) {
1766 $crate::Result::Ok(Self {
1767 ident
1768 })
1769 } else {
1770 $crate::Result::Err(input.unexpected_token(
1771 ::std::collections::HashSet::from_iter([::core::stringify!($kw).to_string()]),
1772 ))
1773 }
1774 }
1775 }
1776
1777 impl $crate::private::Sealed for $name {}
1778
1779 impl $crate::token::Token for $name {
1780 fn span(&self) -> &$crate::Span {
1781 self.ident.span()
1782 }
1783
1784 fn set_span(&mut self, span: $crate::Span) {
1785 self.ident.set_span(span);
1786 }
1787
1788 fn display() -> String {
1789 ::core::stringify!($kw).to_string()
1790 }
1791 }
1792
1793 impl ::core::cmp::PartialEq for $name {
1794 fn eq(&self, _: &Self) -> bool {
1795 true
1796 }
1797 }
1798
1799 impl ::core::cmp::Eq for $name {}
1800
1801 impl ::core::cmp::PartialOrd for $name {
1802 fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> {
1803 ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
1804 }
1805 }
1806
1807 impl ::core::cmp::Ord for $name {
1808 fn cmp(&self, _: &Self) -> ::core::cmp::Ordering {
1809 ::core::cmp::Ordering::Equal
1810 }
1811 }
1812
1813 #[doc(hidden)]
1814 #[allow(dead_code)]
1815 pub const fn $name(marker: $crate::private::Marker) -> $name {
1816 match marker {}
1817 }
1818 };
1819}
1820
1821#[macro_export]
1836macro_rules! Punct {
1837 ["&"] => { $crate::token::Ampersand };
1838 ["&&"] => { $crate::token::AmpersandAmpersand };
1839 ["*"] => { $crate::token::Asterisk };
1840 ["*="] => { $crate::token::AsteriskEqual };
1841 ["@"] => { $crate::token::At };
1842 ["\\"] => { $crate::token::Backslash };
1843 ["`"] => { $crate::token::BackTick };
1844 ["!"] => { $crate::token::Bang };
1845 ["!="] => { $crate::token::BangEqual };
1846 ["^"] => { $crate::token::Caret };
1847 [":"] => { $crate::token::Colon };
1848 ["::"] => { $crate::token::ColonColon };
1849 ["::"] => { $crate::token::ColonColonEqual };
1850 [","] => { $crate::token::Comma };
1851 ["-"] => { $crate::token::Dash };
1852 ["--"] => { $crate::token::DashDash };
1853 ["-="] => { $crate::token::DashEqual };
1854 ["$"] => { $crate::token::Dollar };
1855 ["."] => { $crate::token::Dot };
1856 ["\""] => { $crate::token::DoubleQuote };
1857 ["="] => { $crate::token::Equal };
1858 ["=="] => { $crate::token::EqualEqual };
1859 ["=>"] => { $crate::token::FatArrow };
1860 ["#"] => { $crate::token::Hash };
1861 ["##"] => { $crate::token::HashHash };
1862 ["###"] => { $crate::token::HashHashHash };
1863 ["<"] => { $crate::token::LAngle };
1864 ["<="] => { $crate::token::LAngleEqual };
1865 ["<<"] => { $crate::token::LAngleLAngle };
1866 ["<<="] => { $crate::token::LAngleLAngleEqual };
1867 ["<-"] => { $crate::token::LThinArrow };
1868 ["{"] => { $crate::token::LeftBrace };
1869 ["["] => { $crate::token::LeftBracket };
1870 ["("] => { $crate::token::LeftParen };
1871 ["\n"] => { $crate::token::NewLine };
1872 ["%"] => { $crate::token::Percent };
1873 ["%="] => { $crate::token::PercentEqual };
1874 ["|"] => { $crate::token::Pipe };
1875 ["||"] => { $crate::token::PipePipe };
1876 ["+"] => { $crate::token::Plus };
1877 ["+="] => { $crate::token::PlusEqual };
1878 ["++"] => { $crate::token::PlusPlus };
1879 ["£"] => { $crate::token::Pound };
1880 ["?"] => { $crate::token::Question };
1881 [">"] => { $crate::token::RAngle };
1882 [">="] => { $crate::token::RAngleEqual };
1883 [">>"] => { $crate::token::RAngleRAngle };
1884 [">>="] => { $crate::token::RAngleRAngleEqual };
1885 ["->"] => { $crate::token::RThinArrow };
1886 ["}"] => { $crate::token::RightBrace };
1887 ["]"] => { $crate::token::RightBracket };
1888 [")"] => { $crate::token::RightParen };
1889 [";"] => { $crate::token::SemiColon };
1890 ["'"] => { $crate::token::SingleQuote };
1891 ["/"] => { $crate::token::Slash };
1892 ["/="] => { $crate::token::SlashEqual };
1893 ["//"] => { $crate::token::SlashSlash };
1894 ["//="] => { $crate::token::SlashSlashEqual };
1895 [" "] => { $crate::token::Space2 };
1896 [" "] => { $crate::token::Space4 };
1897 ["\t"] => { $crate::token::Tab };
1898 ["~"] => { $crate::token::Tilde };
1899 ["¬"] => { $crate::token::Tilde2 };
1900 ["_"] => { $crate::token::UnderScore };
1901 [$l:tt, $( $r:tt ),+] => {
1902 ($crate::Punct![impl $l, $( $r ),+], $crate::Span)
1903 };
1904 [impl $l:tt] => { ($crate::Punct![$l],) };
1905 [impl $l:tt, $( $r:tt ),+] => {
1906 (($crate::Punct![$l],), $crate::Punct![impl $( $r ),+])
1907 };
1908}