flexi_parse/
token.rs

1//! Tokens representing punctuation, identifiers, keywords, and whitespace.
2//!
3//! Types for parsing delimited groups can be found in the
4//! [`group`](mod@crate::group) module.
5//!
6//! The punctuation tokens can be most easily accessed using the
7//! [`Punct`](crate::Punct) macro.
8
9use 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
34/// A trait for types that can be represented by a single token.
35///
36/// This trait is sealed, and cannot be implemented by types outside of this
37/// crate.
38pub trait Token: Parse + fmt::Debug + Sealed {
39    /// Returns the span covered by this token.
40    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
63/// A trait for punctuation tokens.
64///
65/// This trait is sealed, and cannot be implemented by types outside of this
66/// crate.
67pub trait Punct: Token {
68    #[doc(hidden)]
69    fn peek(input: ParseStream<'_>) -> bool;
70}
71
72/// A string literal delimited by double quotes.
73///
74/// See also [`DoubleQuotes`].
75#[derive(Debug, Clone)]
76pub struct LitStrDoubleQuote {
77    string: String,
78    span: Span,
79}
80
81impl LitStrDoubleQuote {
82    /// Returns the string within the quotes of this literal.
83    pub const fn string(&self) -> &String {
84        &self.string
85    }
86
87    /// Constructs a new `LitStrDoubleQuote` with the given value and span.
88    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/// A string literal delimited by single quotes.
161///
162/// See also [`SingleQuotes`].
163#[derive(Debug, Clone)]
164pub struct LitStrSingleQuote {
165    string: String,
166    span: Span,
167}
168
169impl LitStrSingleQuote {
170    /// Returns the string within the quotes of this literal.
171    pub const fn string(&self) -> &String {
172        &self.string
173    }
174
175    /// Constructs a new `LitStrSingleQuote` with the given value and span.
176    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/// A character literal delimited by single quotes.
249///
250/// See also [`SingleQuotes`].
251#[derive(Debug, Clone)]
252pub struct LitChar {
253    ch: char,
254    span: Span,
255}
256
257impl LitChar {
258    /// Returns the character within this literal.
259    pub const fn ch(&self) -> char {
260        self.ch
261    }
262
263    /// Constructs a new `LitChar` with the given value and span.
264    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/// An identifier consisting of alphanumeric characters and underscores, and
338/// starting with an alphabetic character or an underscore.
339#[derive(Debug, Clone)]
340pub struct Ident {
341    pub(crate) string: String,
342    pub(crate) span: Span,
343}
344
345impl Ident {
346    /// Returns the text that makes up the identifier.
347    pub const fn string(&self) -> &String {
348        &self.string
349    }
350
351    /// Creates a new identifier in the given [`ParseStream`] with the given
352    /// string.
353    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/// An integer literal.
528///
529/// The default parsing implementation accepts either a string of ascii digits,
530/// or `0b`, `0o`, or `0x`, followed by a number in base 2, 8, or 16
531/// respectively.
532#[derive(Debug, Clone)]
533pub struct LitInt {
534    value: u64,
535    span: Span,
536}
537
538impl LitInt {
539    /// Returns the value of this literal.
540    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    /// Parses a base 10 integer.
553    ///
554    /// ## Errors
555    /// Returns an error if the input is not a base 10 integer.
556    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    /// Constructs a new `LitInt` with the given value and span.
563    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)] // Should probably warn on this.
651fn 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/// A string of ascii digits followed by a `.`, and then another string of
666/// ascii digits.
667#[derive(Debug, Clone)]
668pub struct LitFloat {
669    value: f64,
670    span: Span,
671}
672
673impl LitFloat {
674    /// Returns the value of this literal.
675    pub const fn value(&self) -> f64 {
676        self.value
677    }
678
679    /// Constructs a new `LitFloat` with the given value and span.
680    pub const fn new(value: f64, span: Span) -> LitFloat {
681        LitFloat { value, span }
682    }
683
684    #[allow(clippy::cast_precision_loss)] // Should probably warn on this.
685    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                /// The span covered by this token.
756                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                /// The span covered by this token.
894                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                /// The span covered by this token.
1036                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/// `  `
1377#[derive(Debug, Clone)]
1378pub struct Space2 {
1379    /// The span covered by this token.
1380    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/// `    `
1441#[derive(Debug, Clone)]
1442pub struct Space4 {
1443    /// The span covered by this token.
1444    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/// `\t`
1515#[derive(Debug, Clone)]
1516pub struct Tab {
1517    /// The span covered by this token.
1518    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/// `\n`
1578#[derive(Debug, Clone)]
1579pub struct NewLine {
1580    /// The span covered by this token.
1581    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/// `u+000D`
1641#[derive(Debug, Clone)]
1642pub struct CarriageReturn {
1643    /// The span covered by this token.
1644    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/// Generate types for keywords.
1704///
1705/// ## Usage
1706/// ```
1707/// use flexi_parse::parse_string;
1708/// mod kw {
1709///     use flexi_parse::keywords;
1710///     keywords![var, then];
1711/// }
1712///
1713/// # fn main() {
1714/// let kw1: kw::var = parse_string("var".to_string()).unwrap();
1715/// let kw2: kw::then = parse_string("then".to_string()).unwrap();
1716/// # }
1717/// ```
1718#[macro_export]
1719macro_rules! keywords {
1720    [ $( $kw:ident $(as $name:ident)? ),+ $(,)? ] => {
1721        $(
1722            $crate::keywords!(@ $kw $(as $name)?);
1723        )+
1724
1725        /// Parses non-keyword identifiers.
1726        #[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/// A macro to get the type of a punctuation token.
1822///
1823/// To avoid ambiguity, whitespace tokens are not available through this this
1824/// macro. Instead, use them directly, such as in `token::Space4`.
1825///
1826/// If the punctuation you want is not recognised by this macro, split it into
1827/// its constituent parts, e.g. `Punct!["£", "$"]` for `£$` or
1828/// `Punct!["++", "-"]` for `++-`.
1829///
1830/// Note that unlike [`syn::Token`], this macro accepts the token as a quoted
1831/// string. This allows tokens not recognised by the Rust scanner to be
1832/// accessed with this macro.
1833///
1834/// [`syn::Token`]: https://docs.rs/syn/latest/syn/macro.Token.html
1835#[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}