syn/
token.rs

1//! Tokens representing Rust punctuation, keywords, and delimiters.
2//!
3//! The type names in this module can be difficult to keep straight, so we
4//! prefer to use the [`Token!`] macro instead. This is a type-macro that
5//! expands to the token type of the given token.
6//!
7//! [`Token!`]: crate::Token
8//!
9//! # Example
10//!
11//! The [`ItemStatic`] syntax tree node is defined like this.
12//!
13//! [`ItemStatic`]: crate::ItemStatic
14//!
15//! ```
16//! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
17//! #
18//! pub struct ItemStatic {
19//!     pub attrs: Vec<Attribute>,
20//!     pub vis: Visibility,
21//!     pub static_token: Token![static],
22//!     pub mutability: Option<Token![mut]>,
23//!     pub ident: Ident,
24//!     pub colon_token: Token![:],
25//!     pub ty: Box<Type>,
26//!     pub eq_token: Token![=],
27//!     pub expr: Box<Expr>,
28//!     pub semi_token: Token![;],
29//! }
30//! ```
31//!
32//! # Parsing
33//!
34//! Keywords and punctuation can be parsed through the [`ParseStream::parse`]
35//! method. Delimiter tokens are parsed using the [`parenthesized!`],
36//! [`bracketed!`] and [`braced!`] macros.
37//!
38//! [`ParseStream::parse`]: crate::parse::ParseBuffer::parse()
39//! [`parenthesized!`]: crate::parenthesized!
40//! [`bracketed!`]: crate::bracketed!
41//! [`braced!`]: crate::braced!
42//!
43//! ```
44//! use syn::{Attribute, Result};
45//! use syn::parse::{Parse, ParseStream};
46//! #
47//! # enum ItemStatic {}
48//!
49//! // Parse the ItemStatic struct shown above.
50//! impl Parse for ItemStatic {
51//!     fn parse(input: ParseStream) -> Result<Self> {
52//!         # use syn::ItemStatic;
53//!         # fn parse(input: ParseStream) -> Result<ItemStatic> {
54//!         Ok(ItemStatic {
55//!             attrs: input.call(Attribute::parse_outer)?,
56//!             vis: input.parse()?,
57//!             static_token: input.parse()?,
58//!             mutability: input.parse()?,
59//!             ident: input.parse()?,
60//!             colon_token: input.parse()?,
61//!             ty: input.parse()?,
62//!             eq_token: input.parse()?,
63//!             expr: input.parse()?,
64//!             semi_token: input.parse()?,
65//!         })
66//!         # }
67//!         # unimplemented!()
68//!     }
69//! }
70//! ```
71//!
72//! # Other operations
73//!
74//! Every keyword and punctuation token supports the following operations.
75//!
76//! - [Peeking] — `input.peek(Token![...])`
77//!
78//! - [Parsing] — `input.parse::<Token![...]>()?`
79//!
80//! - [Printing] — `quote!( ... #the_token ... )`
81//!
82//! - Construction from a [`Span`] — `let the_token = Token![...](sp)`
83//!
84//! - Field access to its span — `let sp = the_token.span`
85//!
86//! [Peeking]: crate::parse::ParseBuffer::peek()
87//! [Parsing]: crate::parse::ParseBuffer::parse()
88//! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html
89//! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html
90
91#[cfg(feature = "parsing")]
92pub(crate) use self::private::CustomToken;
93use self::private::WithSpan;
94#[cfg(feature = "parsing")]
95use crate::buffer::Cursor;
96#[cfg(feature = "parsing")]
97use crate::error::Result;
98#[cfg(feature = "parsing")]
99use crate::lifetime::Lifetime;
100#[cfg(feature = "parsing")]
101use crate::parse::{Parse, ParseStream};
102use crate::span::IntoSpans;
103use proc_macro2::extra::DelimSpan;
104use proc_macro2::Span;
105#[cfg(feature = "printing")]
106use proc_macro2::TokenStream;
107#[cfg(any(feature = "parsing", feature = "printing"))]
108use proc_macro2::{Delimiter, Ident};
109#[cfg(feature = "parsing")]
110use proc_macro2::{Literal, Punct, TokenTree};
111#[cfg(feature = "printing")]
112use quote::{ToTokens, TokenStreamExt};
113#[cfg(feature = "extra-traits")]
114use std::cmp;
115#[cfg(feature = "extra-traits")]
116use std::fmt::{self, Debug};
117#[cfg(feature = "extra-traits")]
118use std::hash::{Hash, Hasher};
119use std::ops::{Deref, DerefMut};
120
121/// Marker trait for types that represent single tokens.
122///
123/// This trait is sealed and cannot be implemented for types outside of Syn.
124#[cfg(feature = "parsing")]
125pub trait Token: private::Sealed {
126    // Not public API.
127    #[doc(hidden)]
128    fn peek(cursor: Cursor) -> bool;
129
130    // Not public API.
131    #[doc(hidden)]
132    fn display() -> &'static str;
133}
134
135pub(crate) mod private {
136    #[cfg(feature = "parsing")]
137    use crate::buffer::Cursor;
138    use proc_macro2::Span;
139
140    #[cfg(feature = "parsing")]
141    pub trait Sealed {}
142
143    /// Support writing `token.span` rather than `token.spans[0]` on tokens that
144    /// hold a single span.
145    #[repr(transparent)]
146    #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482
147    pub struct WithSpan {
148        pub span: Span,
149    }
150
151    // Not public API.
152    #[doc(hidden)]
153    #[cfg(feature = "parsing")]
154    pub trait CustomToken {
155        fn peek(cursor: Cursor) -> bool;
156        fn display() -> &'static str;
157    }
158}
159
160#[cfg(feature = "parsing")]
161impl private::Sealed for Ident {}
162
163macro_rules! impl_low_level_token {
164    ($display:literal $($path:ident)::+ $get:ident) => {
165        #[cfg(feature = "parsing")]
166        impl Token for $($path)::+ {
167            fn peek(cursor: Cursor) -> bool {
168                cursor.$get().is_some()
169            }
170
171            fn display() -> &'static str {
172                $display
173            }
174        }
175
176        #[cfg(feature = "parsing")]
177        impl private::Sealed for $($path)::+ {}
178    };
179}
180
181impl_low_level_token!("punctuation token" Punct punct);
182impl_low_level_token!("literal" Literal literal);
183impl_low_level_token!("token" TokenTree token_tree);
184impl_low_level_token!("group token" proc_macro2::Group any_group);
185impl_low_level_token!("lifetime" Lifetime lifetime);
186
187#[cfg(feature = "parsing")]
188impl<T: CustomToken> private::Sealed for T {}
189
190#[cfg(feature = "parsing")]
191impl<T: CustomToken> Token for T {
192    fn peek(cursor: Cursor) -> bool {
193        <Self as CustomToken>::peek(cursor)
194    }
195
196    fn display() -> &'static str {
197        <Self as CustomToken>::display()
198    }
199}
200
201macro_rules! define_keywords {
202    ($($token:literal pub struct $name:ident)*) => {
203        $(
204            #[doc = concat!('`', $token, '`')]
205            ///
206            /// Don't try to remember the name of this type &mdash; use the
207            /// [`Token!`] macro instead.
208            ///
209            /// [`Token!`]: crate::token
210            pub struct $name {
211                pub span: Span,
212            }
213
214            #[doc(hidden)]
215            #[allow(non_snake_case)]
216            pub fn $name<S: IntoSpans<Span>>(span: S) -> $name {
217                $name {
218                    span: span.into_spans(),
219                }
220            }
221
222            impl std::default::Default for $name {
223                fn default() -> Self {
224                    $name {
225                        span: Span::call_site(),
226                    }
227                }
228            }
229
230            #[cfg(feature = "clone-impls")]
231            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
232            impl Copy for $name {}
233
234            #[cfg(feature = "clone-impls")]
235            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
236            impl Clone for $name {
237                fn clone(&self) -> Self {
238                    *self
239                }
240            }
241
242            #[cfg(feature = "extra-traits")]
243            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
244            impl Debug for $name {
245                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246                    f.write_str(stringify!($name))
247                }
248            }
249
250            #[cfg(feature = "extra-traits")]
251            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
252            impl cmp::Eq for $name {}
253
254            #[cfg(feature = "extra-traits")]
255            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
256            impl PartialEq for $name {
257                fn eq(&self, _other: &$name) -> bool {
258                    true
259                }
260            }
261
262            #[cfg(feature = "extra-traits")]
263            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
264            impl Hash for $name {
265                fn hash<H: Hasher>(&self, _state: &mut H) {}
266            }
267
268            #[cfg(feature = "printing")]
269            #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
270            impl ToTokens for $name {
271                fn to_tokens(&self, tokens: &mut TokenStream) {
272                    printing::keyword($token, self.span, tokens);
273                }
274            }
275
276            #[cfg(feature = "parsing")]
277            #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
278            impl Parse for $name {
279                fn parse(input: ParseStream) -> Result<Self> {
280                    Ok($name {
281                        span: parsing::keyword(input, $token)?,
282                    })
283                }
284            }
285
286            #[cfg(feature = "parsing")]
287            impl Token for $name {
288                fn peek(cursor: Cursor) -> bool {
289                    parsing::peek_keyword(cursor, $token)
290                }
291
292                fn display() -> &'static str {
293                    concat!("`", $token, "`")
294                }
295            }
296
297            #[cfg(feature = "parsing")]
298            impl private::Sealed for $name {}
299        )*
300    };
301}
302
303macro_rules! impl_deref_if_len_is_1 {
304    ($name:ident/1) => {
305        impl Deref for $name {
306            type Target = WithSpan;
307
308            fn deref(&self) -> &Self::Target {
309                unsafe { &*(self as *const Self).cast::<WithSpan>() }
310            }
311        }
312
313        impl DerefMut for $name {
314            fn deref_mut(&mut self) -> &mut Self::Target {
315                unsafe { &mut *(self as *mut Self).cast::<WithSpan>() }
316            }
317        }
318    };
319
320    ($name:ident/$len:literal) => {};
321}
322
323macro_rules! define_punctuation_structs {
324    ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
325        $(
326            #[cfg_attr(not(doc), repr(transparent))]
327            #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482
328            #[doc = concat!('`', $token, '`')]
329            ///
330            /// Usage:
331            #[doc = concat!($usage, '.')]
332            ///
333            /// Don't try to remember the name of this type &mdash; use the
334            /// [`Token!`] macro instead.
335            ///
336            /// [`Token!`]: crate::token
337            pub struct $name {
338                pub spans: [Span; $len],
339            }
340
341            #[doc(hidden)]
342            #[allow(non_snake_case)]
343            pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
344                $name {
345                    spans: spans.into_spans(),
346                }
347            }
348
349            impl std::default::Default for $name {
350                fn default() -> Self {
351                    $name {
352                        spans: [Span::call_site(); $len],
353                    }
354                }
355            }
356
357            #[cfg(feature = "clone-impls")]
358            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
359            impl Copy for $name {}
360
361            #[cfg(feature = "clone-impls")]
362            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
363            impl Clone for $name {
364                fn clone(&self) -> Self {
365                    *self
366                }
367            }
368
369            #[cfg(feature = "extra-traits")]
370            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
371            impl Debug for $name {
372                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
373                    f.write_str(stringify!($name))
374                }
375            }
376
377            #[cfg(feature = "extra-traits")]
378            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
379            impl cmp::Eq for $name {}
380
381            #[cfg(feature = "extra-traits")]
382            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
383            impl PartialEq for $name {
384                fn eq(&self, _other: &$name) -> bool {
385                    true
386                }
387            }
388
389            #[cfg(feature = "extra-traits")]
390            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
391            impl Hash for $name {
392                fn hash<H: Hasher>(&self, _state: &mut H) {}
393            }
394
395            impl_deref_if_len_is_1!($name/$len);
396        )*
397    };
398}
399
400macro_rules! define_punctuation {
401    ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
402        $(
403            define_punctuation_structs! {
404                $token pub struct $name/$len #[doc = $usage]
405            }
406
407            #[cfg(feature = "printing")]
408            #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
409            impl ToTokens for $name {
410                fn to_tokens(&self, tokens: &mut TokenStream) {
411                    printing::punct($token, &self.spans, tokens);
412                }
413            }
414
415            #[cfg(feature = "parsing")]
416            #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
417            impl Parse for $name {
418                fn parse(input: ParseStream) -> Result<Self> {
419                    Ok($name {
420                        spans: parsing::punct(input, $token)?,
421                    })
422                }
423            }
424
425            #[cfg(feature = "parsing")]
426            impl Token for $name {
427                fn peek(cursor: Cursor) -> bool {
428                    parsing::peek_punct(cursor, $token)
429                }
430
431                fn display() -> &'static str {
432                    concat!("`", $token, "`")
433                }
434            }
435
436            #[cfg(feature = "parsing")]
437            impl private::Sealed for $name {}
438        )*
439    };
440}
441
442macro_rules! define_delimiters {
443    ($($delim:ident pub struct $name:ident #[$doc:meta])*) => {
444        $(
445            #[$doc]
446            pub struct $name {
447                pub span: DelimSpan,
448            }
449
450            #[doc(hidden)]
451            #[allow(non_snake_case)]
452            pub fn $name<S: IntoSpans<DelimSpan>>(span: S) -> $name {
453                $name {
454                    span: span.into_spans(),
455                }
456            }
457
458            impl std::default::Default for $name {
459                fn default() -> Self {
460                    $name(Span::call_site())
461                }
462            }
463
464            #[cfg(feature = "clone-impls")]
465            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
466            impl Copy for $name {}
467
468            #[cfg(feature = "clone-impls")]
469            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
470            impl Clone for $name {
471                fn clone(&self) -> Self {
472                    *self
473                }
474            }
475
476            #[cfg(feature = "extra-traits")]
477            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
478            impl Debug for $name {
479                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480                    f.write_str(stringify!($name))
481                }
482            }
483
484            #[cfg(feature = "extra-traits")]
485            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
486            impl cmp::Eq for $name {}
487
488            #[cfg(feature = "extra-traits")]
489            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
490            impl PartialEq for $name {
491                fn eq(&self, _other: &$name) -> bool {
492                    true
493                }
494            }
495
496            #[cfg(feature = "extra-traits")]
497            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
498            impl Hash for $name {
499                fn hash<H: Hasher>(&self, _state: &mut H) {}
500            }
501
502            impl $name {
503                #[cfg(feature = "printing")]
504                pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
505                where
506                    F: FnOnce(&mut TokenStream),
507                {
508                    let mut inner = TokenStream::new();
509                    f(&mut inner);
510                    printing::delim(Delimiter::$delim, self.span.join(), tokens, inner);
511                }
512            }
513
514            #[cfg(feature = "parsing")]
515            impl private::Sealed for $name {}
516        )*
517    };
518}
519
520define_punctuation_structs! {
521    "_" pub struct Underscore/1 /// wildcard patterns, inferred types, unnamed items in constants, extern crates, use declarations, and destructuring assignment
522}
523
524#[cfg(feature = "printing")]
525#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
526impl ToTokens for Underscore {
527    fn to_tokens(&self, tokens: &mut TokenStream) {
528        tokens.append(Ident::new("_", self.span));
529    }
530}
531
532#[cfg(feature = "parsing")]
533#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
534impl Parse for Underscore {
535    fn parse(input: ParseStream) -> Result<Self> {
536        input.step(|cursor| {
537            if let Some((ident, rest)) = cursor.ident() {
538                if ident == "_" {
539                    return Ok((Underscore(ident.span()), rest));
540                }
541            }
542            if let Some((punct, rest)) = cursor.punct() {
543                if punct.as_char() == '_' {
544                    return Ok((Underscore(punct.span()), rest));
545                }
546            }
547            Err(cursor.error("expected `_`"))
548        })
549    }
550}
551
552#[cfg(feature = "parsing")]
553impl Token for Underscore {
554    fn peek(cursor: Cursor) -> bool {
555        if let Some((ident, _rest)) = cursor.ident() {
556            return ident == "_";
557        }
558        if let Some((punct, _rest)) = cursor.punct() {
559            return punct.as_char() == '_';
560        }
561        false
562    }
563
564    fn display() -> &'static str {
565        "`_`"
566    }
567}
568
569#[cfg(feature = "parsing")]
570impl private::Sealed for Underscore {}
571
572/// None-delimited group
573pub struct Group {
574    pub span: Span,
575}
576
577#[doc(hidden)]
578#[allow(non_snake_case)]
579pub fn Group<S: IntoSpans<Span>>(span: S) -> Group {
580    Group {
581        span: span.into_spans(),
582    }
583}
584
585impl std::default::Default for Group {
586    fn default() -> Self {
587        Group {
588            span: Span::call_site(),
589        }
590    }
591}
592
593#[cfg(feature = "clone-impls")]
594#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
595impl Copy for Group {}
596
597#[cfg(feature = "clone-impls")]
598#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
599impl Clone for Group {
600    fn clone(&self) -> Self {
601        *self
602    }
603}
604
605#[cfg(feature = "extra-traits")]
606#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
607impl Debug for Group {
608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609        f.write_str("Group")
610    }
611}
612
613#[cfg(feature = "extra-traits")]
614#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
615impl cmp::Eq for Group {}
616
617#[cfg(feature = "extra-traits")]
618#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
619impl PartialEq for Group {
620    fn eq(&self, _other: &Group) -> bool {
621        true
622    }
623}
624
625#[cfg(feature = "extra-traits")]
626#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
627impl Hash for Group {
628    fn hash<H: Hasher>(&self, _state: &mut H) {}
629}
630
631impl Group {
632    #[cfg(feature = "printing")]
633    pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
634    where
635        F: FnOnce(&mut TokenStream),
636    {
637        let mut inner = TokenStream::new();
638        f(&mut inner);
639        printing::delim(Delimiter::None, self.span, tokens, inner);
640    }
641}
642
643#[cfg(feature = "parsing")]
644impl private::Sealed for Group {}
645
646#[cfg(feature = "parsing")]
647impl Token for Paren {
648    fn peek(cursor: Cursor) -> bool {
649        cursor.group(Delimiter::Parenthesis).is_some()
650    }
651
652    fn display() -> &'static str {
653        "parentheses"
654    }
655}
656
657#[cfg(feature = "parsing")]
658impl Token for Brace {
659    fn peek(cursor: Cursor) -> bool {
660        cursor.group(Delimiter::Brace).is_some()
661    }
662
663    fn display() -> &'static str {
664        "curly braces"
665    }
666}
667
668#[cfg(feature = "parsing")]
669impl Token for Bracket {
670    fn peek(cursor: Cursor) -> bool {
671        cursor.group(Delimiter::Bracket).is_some()
672    }
673
674    fn display() -> &'static str {
675        "square brackets"
676    }
677}
678
679#[cfg(feature = "parsing")]
680impl Token for Group {
681    fn peek(cursor: Cursor) -> bool {
682        cursor.group(Delimiter::None).is_some()
683    }
684
685    fn display() -> &'static str {
686        "invisible group"
687    }
688}
689
690define_keywords! {
691    "abstract"    pub struct Abstract
692    "as"          pub struct As
693    "async"       pub struct Async
694    "auto"        pub struct Auto
695    "await"       pub struct Await
696    "become"      pub struct Become
697    "box"         pub struct Box
698    "break"       pub struct Break
699    "const"       pub struct Const
700    "continue"    pub struct Continue
701    "crate"       pub struct Crate
702    "default"     pub struct Default
703    "do"          pub struct Do
704    "dyn"         pub struct Dyn
705    "else"        pub struct Else
706    "enum"        pub struct Enum
707    "extern"      pub struct Extern
708    "final"       pub struct Final
709    "fn"          pub struct Fn
710    "for"         pub struct For
711    "if"          pub struct If
712    "impl"        pub struct Impl
713    "in"          pub struct In
714    "let"         pub struct Let
715    "loop"        pub struct Loop
716    "macro"       pub struct Macro
717    "match"       pub struct Match
718    "mod"         pub struct Mod
719    "move"        pub struct Move
720    "mut"         pub struct Mut
721    "override"    pub struct Override
722    "priv"        pub struct Priv
723    "pub"         pub struct Pub
724    "raw"         pub struct Raw
725    "ref"         pub struct Ref
726    "return"      pub struct Return
727    "Self"        pub struct SelfType
728    "self"        pub struct SelfValue
729    "static"      pub struct Static
730    "struct"      pub struct Struct
731    "super"       pub struct Super
732    "trait"       pub struct Trait
733    "try"         pub struct Try
734    "type"        pub struct Type
735    "typeof"      pub struct Typeof
736    "union"       pub struct Union
737    "unsafe"      pub struct Unsafe
738    "unsized"     pub struct Unsized
739    "use"         pub struct Use
740    "virtual"     pub struct Virtual
741    "where"       pub struct Where
742    "while"       pub struct While
743    "yield"       pub struct Yield
744}
745
746define_punctuation! {
747    "&"           pub struct And/1        /// bitwise and logical AND, borrow, references, reference patterns
748    "&&"          pub struct AndAnd/2     /// lazy AND, borrow, references, reference patterns
749    "&="          pub struct AndEq/2      /// bitwise AND assignment
750    "@"           pub struct At/1         /// subpattern binding
751    "^"           pub struct Caret/1      /// bitwise and logical XOR
752    "^="          pub struct CaretEq/2    /// bitwise XOR assignment
753    ":"           pub struct Colon/1      /// various separators
754    ","           pub struct Comma/1      /// various separators
755    "$"           pub struct Dollar/1     /// macros
756    "."           pub struct Dot/1        /// field access, tuple index
757    ".."          pub struct DotDot/2     /// range, struct expressions, patterns, range patterns
758    "..."         pub struct DotDotDot/3  /// variadic functions, range patterns
759    "..="         pub struct DotDotEq/3   /// inclusive range, range patterns
760    "="           pub struct Eq/1         /// assignment, attributes, various type definitions
761    "=="          pub struct EqEq/2       /// equal
762    "=>"          pub struct FatArrow/2   /// match arms, macros
763    ">="          pub struct Ge/2         /// greater than or equal to, generics
764    ">"           pub struct Gt/1         /// greater than, generics, paths
765    "<-"          pub struct LArrow/2     /// unused
766    "<="          pub struct Le/2         /// less than or equal to
767    "<"           pub struct Lt/1         /// less than, generics, paths
768    "-"           pub struct Minus/1      /// subtraction, negation
769    "-="          pub struct MinusEq/2    /// subtraction assignment
770    "!="          pub struct Ne/2         /// not equal
771    "!"           pub struct Not/1        /// bitwise and logical NOT, macro calls, inner attributes, never type, negative impls
772    "|"           pub struct Or/1         /// bitwise and logical OR, closures, patterns in match, if let, and while let
773    "|="          pub struct OrEq/2       /// bitwise OR assignment
774    "||"          pub struct OrOr/2       /// lazy OR, closures
775    "::"          pub struct PathSep/2    /// path separator
776    "%"           pub struct Percent/1    /// remainder
777    "%="          pub struct PercentEq/2  /// remainder assignment
778    "+"           pub struct Plus/1       /// addition, trait bounds, macro Kleene matcher
779    "+="          pub struct PlusEq/2     /// addition assignment
780    "#"           pub struct Pound/1      /// attributes
781    "?"           pub struct Question/1   /// question mark operator, questionably sized, macro Kleene matcher
782    "->"          pub struct RArrow/2     /// function return type, closure return type, function pointer type
783    ";"           pub struct Semi/1       /// terminator for various items and statements, array types
784    "<<"          pub struct Shl/2        /// shift left, nested generics
785    "<<="         pub struct ShlEq/3      /// shift left assignment
786    ">>"          pub struct Shr/2        /// shift right, nested generics
787    ">>="         pub struct ShrEq/3      /// shift right assignment, nested generics
788    "/"           pub struct Slash/1      /// division
789    "/="          pub struct SlashEq/2    /// division assignment
790    "*"           pub struct Star/1       /// multiplication, dereference, raw pointers, macro Kleene matcher, use wildcards
791    "*="          pub struct StarEq/2     /// multiplication assignment
792    "~"           pub struct Tilde/1      /// unused since before Rust 1.0
793}
794
795define_delimiters! {
796    Brace         pub struct Brace        /// `{`&hellip;`}`
797    Bracket       pub struct Bracket      /// `[`&hellip;`]`
798    Parenthesis   pub struct Paren        /// `(`&hellip;`)`
799}
800
801/// A type-macro that expands to the name of the Rust type representation of a
802/// given token.
803///
804/// As a type, `Token!` is commonly used in the type of struct fields, the type
805/// of a `let` statement, or in turbofish for a `parse` function.
806///
807/// ```
808/// use syn::{Ident, Token};
809/// use syn::parse::{Parse, ParseStream, Result};
810///
811/// // `struct Foo;`
812/// pub struct UnitStruct {
813///     struct_token: Token![struct],
814///     ident: Ident,
815///     semi_token: Token![;],
816/// }
817///
818/// impl Parse for UnitStruct {
819///     fn parse(input: ParseStream) -> Result<Self> {
820///         let struct_token: Token![struct] = input.parse()?;
821///         let ident: Ident = input.parse()?;
822///         let semi_token = input.parse::<Token![;]>()?;
823///         Ok(UnitStruct { struct_token, ident, semi_token })
824///     }
825/// }
826/// ```
827///
828/// As an expression, `Token!` is used for peeking tokens or instantiating
829/// tokens from a span.
830///
831/// ```
832/// # use syn::{Ident, Token};
833/// # use syn::parse::{Parse, ParseStream, Result};
834/// #
835/// # struct UnitStruct {
836/// #     struct_token: Token![struct],
837/// #     ident: Ident,
838/// #     semi_token: Token![;],
839/// # }
840/// #
841/// # impl Parse for UnitStruct {
842/// #     fn parse(input: ParseStream) -> Result<Self> {
843/// #         unimplemented!()
844/// #     }
845/// # }
846/// #
847/// fn make_unit_struct(name: Ident) -> UnitStruct {
848///     let span = name.span();
849///     UnitStruct {
850///         struct_token: Token![struct](span),
851///         ident: name,
852///         semi_token: Token![;](span),
853///     }
854/// }
855///
856/// # fn parse(input: ParseStream) -> Result<()> {
857/// if input.peek(Token![struct]) {
858///     let unit_struct: UnitStruct = input.parse()?;
859///     /* ... */
860/// }
861/// # Ok(())
862/// # }
863/// ```
864///
865/// See the [token module] documentation for details and examples.
866///
867/// [token module]: crate::token
868#[macro_export]
869macro_rules! Token {
870    [abstract]    => { $crate::token::Abstract };
871    [as]          => { $crate::token::As };
872    [async]       => { $crate::token::Async };
873    [auto]        => { $crate::token::Auto };
874    [await]       => { $crate::token::Await };
875    [become]      => { $crate::token::Become };
876    [box]         => { $crate::token::Box };
877    [break]       => { $crate::token::Break };
878    [const]       => { $crate::token::Const };
879    [continue]    => { $crate::token::Continue };
880    [crate]       => { $crate::token::Crate };
881    [default]     => { $crate::token::Default };
882    [do]          => { $crate::token::Do };
883    [dyn]         => { $crate::token::Dyn };
884    [else]        => { $crate::token::Else };
885    [enum]        => { $crate::token::Enum };
886    [extern]      => { $crate::token::Extern };
887    [final]       => { $crate::token::Final };
888    [fn]          => { $crate::token::Fn };
889    [for]         => { $crate::token::For };
890    [if]          => { $crate::token::If };
891    [impl]        => { $crate::token::Impl };
892    [in]          => { $crate::token::In };
893    [let]         => { $crate::token::Let };
894    [loop]        => { $crate::token::Loop };
895    [macro]       => { $crate::token::Macro };
896    [match]       => { $crate::token::Match };
897    [mod]         => { $crate::token::Mod };
898    [move]        => { $crate::token::Move };
899    [mut]         => { $crate::token::Mut };
900    [override]    => { $crate::token::Override };
901    [priv]        => { $crate::token::Priv };
902    [pub]         => { $crate::token::Pub };
903    [raw]         => { $crate::token::Raw };
904    [ref]         => { $crate::token::Ref };
905    [return]      => { $crate::token::Return };
906    [Self]        => { $crate::token::SelfType };
907    [self]        => { $crate::token::SelfValue };
908    [static]      => { $crate::token::Static };
909    [struct]      => { $crate::token::Struct };
910    [super]       => { $crate::token::Super };
911    [trait]       => { $crate::token::Trait };
912    [try]         => { $crate::token::Try };
913    [type]        => { $crate::token::Type };
914    [typeof]      => { $crate::token::Typeof };
915    [union]       => { $crate::token::Union };
916    [unsafe]      => { $crate::token::Unsafe };
917    [unsized]     => { $crate::token::Unsized };
918    [use]         => { $crate::token::Use };
919    [virtual]     => { $crate::token::Virtual };
920    [where]       => { $crate::token::Where };
921    [while]       => { $crate::token::While };
922    [yield]       => { $crate::token::Yield };
923    [&]           => { $crate::token::And };
924    [&&]          => { $crate::token::AndAnd };
925    [&=]          => { $crate::token::AndEq };
926    [@]           => { $crate::token::At };
927    [^]           => { $crate::token::Caret };
928    [^=]          => { $crate::token::CaretEq };
929    [:]           => { $crate::token::Colon };
930    [,]           => { $crate::token::Comma };
931    [$]           => { $crate::token::Dollar };
932    [.]           => { $crate::token::Dot };
933    [..]          => { $crate::token::DotDot };
934    [...]         => { $crate::token::DotDotDot };
935    [..=]         => { $crate::token::DotDotEq };
936    [=]           => { $crate::token::Eq };
937    [==]          => { $crate::token::EqEq };
938    [=>]          => { $crate::token::FatArrow };
939    [>=]          => { $crate::token::Ge };
940    [>]           => { $crate::token::Gt };
941    [<-]          => { $crate::token::LArrow };
942    [<=]          => { $crate::token::Le };
943    [<]           => { $crate::token::Lt };
944    [-]           => { $crate::token::Minus };
945    [-=]          => { $crate::token::MinusEq };
946    [!=]          => { $crate::token::Ne };
947    [!]           => { $crate::token::Not };
948    [|]           => { $crate::token::Or };
949    [|=]          => { $crate::token::OrEq };
950    [||]          => { $crate::token::OrOr };
951    [::]          => { $crate::token::PathSep };
952    [%]           => { $crate::token::Percent };
953    [%=]          => { $crate::token::PercentEq };
954    [+]           => { $crate::token::Plus };
955    [+=]          => { $crate::token::PlusEq };
956    [#]           => { $crate::token::Pound };
957    [?]           => { $crate::token::Question };
958    [->]          => { $crate::token::RArrow };
959    [;]           => { $crate::token::Semi };
960    [<<]          => { $crate::token::Shl };
961    [<<=]         => { $crate::token::ShlEq };
962    [>>]          => { $crate::token::Shr };
963    [>>=]         => { $crate::token::ShrEq };
964    [/]           => { $crate::token::Slash };
965    [/=]          => { $crate::token::SlashEq };
966    [*]           => { $crate::token::Star };
967    [*=]          => { $crate::token::StarEq };
968    [~]           => { $crate::token::Tilde };
969    [_]           => { $crate::token::Underscore };
970}
971
972// Not public API.
973#[doc(hidden)]
974#[cfg(feature = "parsing")]
975pub(crate) mod parsing {
976    use crate::buffer::Cursor;
977    use crate::error::{Error, Result};
978    use crate::parse::ParseStream;
979    use proc_macro2::{Spacing, Span};
980
981    pub(crate) fn keyword(input: ParseStream, token: &str) -> Result<Span> {
982        input.step(|cursor| {
983            if let Some((ident, rest)) = cursor.ident() {
984                if ident == token {
985                    return Ok((ident.span(), rest));
986                }
987            }
988            Err(cursor.error(format!("expected `{}`", token)))
989        })
990    }
991
992    pub(crate) fn peek_keyword(cursor: Cursor, token: &str) -> bool {
993        if let Some((ident, _rest)) = cursor.ident() {
994            ident == token
995        } else {
996            false
997        }
998    }
999
1000    #[doc(hidden)]
1001    pub fn punct<const N: usize>(input: ParseStream, token: &str) -> Result<[Span; N]> {
1002        let mut spans = [input.span(); N];
1003        punct_helper(input, token, &mut spans)?;
1004        Ok(spans)
1005    }
1006
1007    fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span]) -> Result<()> {
1008        input.step(|cursor| {
1009            let mut cursor = *cursor;
1010            assert_eq!(token.len(), spans.len());
1011
1012            for (i, ch) in token.chars().enumerate() {
1013                match cursor.punct() {
1014                    Some((punct, rest)) => {
1015                        spans[i] = punct.span();
1016                        if punct.as_char() != ch {
1017                            break;
1018                        } else if i == token.len() - 1 {
1019                            return Ok(((), rest));
1020                        } else if punct.spacing() != Spacing::Joint {
1021                            break;
1022                        }
1023                        cursor = rest;
1024                    }
1025                    None => break,
1026                }
1027            }
1028
1029            Err(Error::new(spans[0], format!("expected `{}`", token)))
1030        })
1031    }
1032
1033    #[doc(hidden)]
1034    pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
1035        for (i, ch) in token.chars().enumerate() {
1036            match cursor.punct() {
1037                Some((punct, rest)) => {
1038                    if punct.as_char() != ch {
1039                        break;
1040                    } else if i == token.len() - 1 {
1041                        return true;
1042                    } else if punct.spacing() != Spacing::Joint {
1043                        break;
1044                    }
1045                    cursor = rest;
1046                }
1047                None => break,
1048            }
1049        }
1050        false
1051    }
1052}
1053
1054// Not public API.
1055#[doc(hidden)]
1056#[cfg(feature = "printing")]
1057pub(crate) mod printing {
1058    use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
1059    use quote::TokenStreamExt;
1060
1061    #[doc(hidden)]
1062    pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
1063        assert_eq!(s.len(), spans.len());
1064
1065        let mut chars = s.chars();
1066        let mut spans = spans.iter();
1067        let ch = chars.next_back().unwrap();
1068        let span = spans.next_back().unwrap();
1069        for (ch, span) in chars.zip(spans) {
1070            let mut op = Punct::new(ch, Spacing::Joint);
1071            op.set_span(*span);
1072            tokens.append(op);
1073        }
1074
1075        let mut op = Punct::new(ch, Spacing::Alone);
1076        op.set_span(*span);
1077        tokens.append(op);
1078    }
1079
1080    pub(crate) fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
1081        tokens.append(Ident::new(s, span));
1082    }
1083
1084    pub(crate) fn delim(
1085        delim: Delimiter,
1086        span: Span,
1087        tokens: &mut TokenStream,
1088        inner: TokenStream,
1089    ) {
1090        let mut g = Group::new(delim, inner);
1091        g.set_span(span);
1092        tokens.append(g);
1093    }
1094}