Skip to main content

syn/
token.rs

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