Skip to main content

syn_impersonated/
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!`]: ../macro.Token.html
8//!
9//! # Example
10//!
11//! The [`ItemStatic`] syntax tree node is defined like this.
12//!
13//! [`ItemStatic`]: ../struct.ItemStatic.html
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`]: ../parse/struct.ParseBuffer.html#method.parse
39//! [`parenthesized!`]: ../macro.parenthesized.html
40//! [`bracketed!`]: ../macro.bracketed.html
41//! [`braced!`]: ../macro.braced.html
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]: ../parse/struct.ParseBuffer.html#method.peek
87//! [Parsing]: ../parse/struct.ParseBuffer.html#method.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 = "extra-traits")]
92use std::cmp;
93#[cfg(feature = "extra-traits")]
94use std::fmt::{self, Debug};
95#[cfg(feature = "extra-traits")]
96use std::hash::{Hash, Hasher};
97use std::ops::{Deref, DerefMut};
98
99#[cfg(feature = "parsing")]
100use proc_macro2::Delimiter;
101#[cfg(any(feature = "parsing", feature = "printing"))]
102use proc_macro2::Ident;
103use proc_macro2::Span;
104#[cfg(feature = "printing")]
105use proc_macro2::TokenStream;
106#[cfg(feature = "printing")]
107use quote::{ToTokens, TokenStreamExt};
108
109use self::private::WithSpan;
110#[cfg(feature = "parsing")]
111use crate::buffer::Cursor;
112#[cfg(feature = "parsing")]
113use crate::error::Result;
114#[cfg(any(feature = "full", feature = "derive"))]
115#[cfg(feature = "parsing")]
116use crate::lifetime::Lifetime;
117#[cfg(any(feature = "full", feature = "derive"))]
118#[cfg(feature = "parsing")]
119use crate::lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
120#[cfg(feature = "parsing")]
121use crate::lookahead;
122#[cfg(feature = "parsing")]
123use crate::parse::{Parse, ParseStream};
124use crate::span::IntoSpans;
125
126/// Marker trait for types that represent single tokens.
127///
128/// This trait is sealed and cannot be implemented for types outside of Syn.
129#[cfg(feature = "parsing")]
130pub trait Token: private::Sealed {
131    // Not public API.
132    #[doc(hidden)]
133    fn peek(cursor: Cursor) -> bool;
134
135    // Not public API.
136    #[doc(hidden)]
137    fn display() -> &'static str;
138}
139
140mod private {
141    use proc_macro2::Span;
142
143    #[cfg(feature = "parsing")]
144    pub trait Sealed {}
145
146    /// Support writing `token.span` rather than `token.spans[0]` on tokens that
147    /// hold a single span.
148    #[repr(C)]
149    pub struct WithSpan {
150        pub span: Span,
151    }
152}
153
154#[cfg(feature = "parsing")]
155impl private::Sealed for Ident {}
156
157#[cfg(any(feature = "full", feature = "derive"))]
158#[cfg(feature = "parsing")]
159fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
160    use crate::parse::Unexpected;
161    use std::cell::Cell;
162    use std::rc::Rc;
163
164    let scope = Span::call_site();
165    let unexpected = Rc::new(Cell::new(Unexpected::None));
166    let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected);
167    peek(&buffer)
168}
169
170#[cfg(any(feature = "full", feature = "derive"))]
171macro_rules! impl_token {
172    ($name:ident $display:expr) => {
173        #[cfg(feature = "parsing")]
174        impl Token for $name {
175            fn peek(cursor: Cursor) -> bool {
176                fn peek(input: ParseStream) -> bool {
177                    <$name as Parse>::parse(input).is_ok()
178                }
179                peek_impl(cursor, peek)
180            }
181
182            fn display() -> &'static str {
183                $display
184            }
185        }
186
187        #[cfg(feature = "parsing")]
188        impl private::Sealed for $name {}
189    };
190}
191
192#[cfg(any(feature = "full", feature = "derive"))]
193impl_token!(Lifetime "lifetime");
194#[cfg(any(feature = "full", feature = "derive"))]
195impl_token!(Lit "literal");
196#[cfg(any(feature = "full", feature = "derive"))]
197impl_token!(LitStr "string literal");
198#[cfg(any(feature = "full", feature = "derive"))]
199impl_token!(LitByteStr "byte string literal");
200#[cfg(any(feature = "full", feature = "derive"))]
201impl_token!(LitByte "byte literal");
202#[cfg(any(feature = "full", feature = "derive"))]
203impl_token!(LitChar "character literal");
204#[cfg(any(feature = "full", feature = "derive"))]
205impl_token!(LitInt "integer literal");
206#[cfg(any(feature = "full", feature = "derive"))]
207impl_token!(LitFloat "floating point literal");
208#[cfg(any(feature = "full", feature = "derive"))]
209impl_token!(LitBool "boolean literal");
210
211// Not public API.
212#[doc(hidden)]
213#[cfg(feature = "parsing")]
214pub trait CustomToken {
215    fn peek(cursor: Cursor) -> bool;
216    fn display() -> &'static str;
217}
218
219#[cfg(feature = "parsing")]
220impl<T: CustomToken> private::Sealed for T {}
221
222#[cfg(feature = "parsing")]
223impl<T: CustomToken> Token for T {
224    fn peek(cursor: Cursor) -> bool {
225        <Self as CustomToken>::peek(cursor)
226    }
227
228    fn display() -> &'static str {
229        <Self as CustomToken>::display()
230    }
231}
232
233macro_rules! define_keywords {
234    ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
235        $(
236            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
237            #[$doc]
238            ///
239            /// Don't try to remember the name of this type &mdash; use the
240            /// [`Token!`] macro instead.
241            ///
242            /// [`Token!`]: crate::token
243            pub struct $name {
244                pub span: Span,
245            }
246
247            #[doc(hidden)]
248            #[allow(non_snake_case)]
249            pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
250                $name {
251                    span: span.into_spans()[0],
252                }
253            }
254
255            impl std::default::Default for $name {
256                fn default() -> Self {
257                    $name {
258                        span: Span::call_site(),
259                    }
260                }
261            }
262
263            #[cfg(feature = "extra-traits")]
264            impl Debug for $name {
265                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266                    f.write_str(stringify!($name))
267                }
268            }
269
270            #[cfg(feature = "extra-traits")]
271            impl cmp::Eq for $name {}
272
273            #[cfg(feature = "extra-traits")]
274            impl PartialEq for $name {
275                fn eq(&self, _other: &$name) -> bool {
276                    true
277                }
278            }
279
280            #[cfg(feature = "extra-traits")]
281            impl Hash for $name {
282                fn hash<H: Hasher>(&self, _state: &mut H) {}
283            }
284
285            #[cfg(feature = "printing")]
286            impl ToTokens for $name {
287                fn to_tokens(&self, tokens: &mut TokenStream) {
288                    printing::keyword($token, self.span, tokens);
289                }
290            }
291
292            #[cfg(feature = "parsing")]
293            impl Parse for $name {
294                fn parse(input: ParseStream) -> Result<Self> {
295                    Ok($name {
296                        span: parsing::keyword(input, $token)?,
297                    })
298                }
299            }
300
301            #[cfg(feature = "parsing")]
302            impl Token for $name {
303                fn peek(cursor: Cursor) -> bool {
304                    parsing::peek_keyword(cursor, $token)
305                }
306
307                fn display() -> &'static str {
308                    concat!("`", $token, "`")
309                }
310            }
311
312            #[cfg(feature = "parsing")]
313            impl private::Sealed for $name {}
314        )*
315    };
316}
317
318macro_rules! impl_deref_if_len_is_1 {
319    ($name:ident/1) => {
320        impl Deref for $name {
321            type Target = WithSpan;
322
323            fn deref(&self) -> &Self::Target {
324                unsafe { &*(self as *const Self as *const WithSpan) }
325            }
326        }
327
328        impl DerefMut for $name {
329            fn deref_mut(&mut self) -> &mut Self::Target {
330                unsafe { &mut *(self as *mut Self as *mut WithSpan) }
331            }
332        }
333    };
334
335    ($name:ident/$len:tt) => {};
336}
337
338macro_rules! define_punctuation_structs {
339    ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
340        $(
341            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
342            #[repr(C)]
343            #[$doc]
344            ///
345            /// Don't try to remember the name of this type &mdash; use the
346            /// [`Token!`] macro instead.
347            ///
348            /// [`Token!`]: crate::token
349            pub struct $name {
350                pub spans: [Span; $len],
351            }
352
353            #[doc(hidden)]
354            #[allow(non_snake_case)]
355            pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
356                $name {
357                    spans: spans.into_spans(),
358                }
359            }
360
361            impl std::default::Default for $name {
362                fn default() -> Self {
363                    $name {
364                        spans: [Span::call_site(); $len],
365                    }
366                }
367            }
368
369            #[cfg(feature = "extra-traits")]
370            impl Debug for $name {
371                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372                    f.write_str(stringify!($name))
373                }
374            }
375
376            #[cfg(feature = "extra-traits")]
377            impl cmp::Eq for $name {}
378
379            #[cfg(feature = "extra-traits")]
380            impl PartialEq for $name {
381                fn eq(&self, _other: &$name) -> bool {
382                    true
383                }
384            }
385
386            #[cfg(feature = "extra-traits")]
387            impl Hash for $name {
388                fn hash<H: Hasher>(&self, _state: &mut H) {}
389            }
390
391            impl_deref_if_len_is_1!($name/$len);
392        )*
393    };
394}
395
396macro_rules! define_punctuation {
397    ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
398        $(
399            define_punctuation_structs! {
400                $token pub struct $name/$len #[$doc]
401            }
402
403            #[cfg(feature = "printing")]
404            impl ToTokens for $name {
405                fn to_tokens(&self, tokens: &mut TokenStream) {
406                    printing::punct($token, &self.spans, tokens);
407                }
408            }
409
410            #[cfg(feature = "parsing")]
411            impl Parse for $name {
412                fn parse(input: ParseStream) -> Result<Self> {
413                    Ok($name {
414                        spans: parsing::punct(input, $token)?,
415                    })
416                }
417            }
418
419            #[cfg(feature = "parsing")]
420            impl Token for $name {
421                fn peek(cursor: Cursor) -> bool {
422                    parsing::peek_punct(cursor, $token)
423                }
424
425                fn display() -> &'static str {
426                    concat!("`", $token, "`")
427                }
428            }
429
430            #[cfg(feature = "parsing")]
431            impl private::Sealed for $name {}
432        )*
433    };
434}
435
436macro_rules! define_delimiters {
437    ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
438        $(
439            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
440            #[$doc]
441            pub struct $name {
442                pub span: Span,
443            }
444
445            #[doc(hidden)]
446            #[allow(non_snake_case)]
447            pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
448                $name {
449                    span: span.into_spans()[0],
450                }
451            }
452
453            impl std::default::Default for $name {
454                fn default() -> Self {
455                    $name {
456                        span: Span::call_site(),
457                    }
458                }
459            }
460
461            #[cfg(feature = "extra-traits")]
462            impl Debug for $name {
463                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
464                    f.write_str(stringify!($name))
465                }
466            }
467
468            #[cfg(feature = "extra-traits")]
469            impl cmp::Eq for $name {}
470
471            #[cfg(feature = "extra-traits")]
472            impl PartialEq for $name {
473                fn eq(&self, _other: &$name) -> bool {
474                    true
475                }
476            }
477
478            #[cfg(feature = "extra-traits")]
479            impl Hash for $name {
480                fn hash<H: Hasher>(&self, _state: &mut H) {}
481            }
482
483            impl $name {
484                #[cfg(feature = "printing")]
485                pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
486                where
487                    F: FnOnce(&mut TokenStream),
488                {
489                    printing::delim($token, self.span, tokens, f);
490                }
491            }
492
493            #[cfg(feature = "parsing")]
494            impl private::Sealed for $name {}
495        )*
496    };
497}
498
499define_punctuation_structs! {
500    "_" pub struct Underscore/1 /// `_`
501}
502
503#[cfg(feature = "printing")]
504impl ToTokens for Underscore {
505    fn to_tokens(&self, tokens: &mut TokenStream) {
506        tokens.append(Ident::new("_", self.span));
507    }
508}
509
510#[cfg(feature = "parsing")]
511impl Parse for Underscore {
512    fn parse(input: ParseStream) -> Result<Self> {
513        input.step(|cursor| {
514            if let Some((ident, rest)) = cursor.ident() {
515                if ident == "_" {
516                    return Ok((Underscore(ident.span()), rest));
517                }
518            }
519            if let Some((punct, rest)) = cursor.punct() {
520                if punct.as_char() == '_' {
521                    return Ok((Underscore(punct.span()), rest));
522                }
523            }
524            Err(cursor.error("expected `_`"))
525        })
526    }
527}
528
529#[cfg(feature = "parsing")]
530impl Token for Underscore {
531    fn peek(cursor: Cursor) -> bool {
532        if let Some((ident, _rest)) = cursor.ident() {
533            return ident == "_";
534        }
535        if let Some((punct, _rest)) = cursor.punct() {
536            return punct.as_char() == '_';
537        }
538        false
539    }
540
541    fn display() -> &'static str {
542        "`_`"
543    }
544}
545
546#[cfg(feature = "parsing")]
547impl private::Sealed for Underscore {}
548
549#[cfg(feature = "parsing")]
550impl Token for Paren {
551    fn peek(cursor: Cursor) -> bool {
552        lookahead::is_delimiter(cursor, Delimiter::Parenthesis)
553    }
554
555    fn display() -> &'static str {
556        "parentheses"
557    }
558}
559
560#[cfg(feature = "parsing")]
561impl Token for Brace {
562    fn peek(cursor: Cursor) -> bool {
563        lookahead::is_delimiter(cursor, Delimiter::Brace)
564    }
565
566    fn display() -> &'static str {
567        "curly braces"
568    }
569}
570
571#[cfg(feature = "parsing")]
572impl Token for Bracket {
573    fn peek(cursor: Cursor) -> bool {
574        lookahead::is_delimiter(cursor, Delimiter::Bracket)
575    }
576
577    fn display() -> &'static str {
578        "square brackets"
579    }
580}
581
582#[cfg(feature = "parsing")]
583impl Token for Group {
584    fn peek(cursor: Cursor) -> bool {
585        lookahead::is_delimiter(cursor, Delimiter::None)
586    }
587
588    fn display() -> &'static str {
589        "invisible group"
590    }
591}
592
593define_keywords! {
594    "abstract"    pub struct Abstract     /// `abstract`
595    "as"          pub struct As           /// `as`
596    "async"       pub struct Async        /// `async`
597    "auto"        pub struct Auto         /// `auto`
598    "await"       pub struct Await        /// `await`
599    "become"      pub struct Become       /// `become`
600    "box"         pub struct Box          /// `box`
601    "break"       pub struct Break        /// `break`
602    "const"       pub struct Const        /// `const`
603    "continue"    pub struct Continue     /// `continue`
604    "crate"       pub struct Crate        /// `crate`
605    "default"     pub struct Default      /// `default`
606    "do"          pub struct Do           /// `do`
607    "dyn"         pub struct Dyn          /// `dyn`
608    "else"        pub struct Else         /// `else`
609    "enum"        pub struct Enum         /// `enum`
610    "extern"      pub struct Extern       /// `extern`
611    "final"       pub struct Final        /// `final`
612    "fn"          pub struct Fn           /// `fn`
613    "for"         pub struct For          /// `for`
614    "if"          pub struct If           /// `if`
615    "impl"        pub struct Impl         /// `impl`
616    "in"          pub struct In           /// `in`
617    "let"         pub struct Let          /// `let`
618    "loop"        pub struct Loop         /// `loop`
619    "macro"       pub struct Macro        /// `macro`
620    "match"       pub struct Match        /// `match`
621    "mod"         pub struct Mod          /// `mod`
622    "move"        pub struct Move         /// `move`
623    "mut"         pub struct Mut          /// `mut`
624    "override"    pub struct Override     /// `override`
625    "priv"        pub struct Priv         /// `priv`
626    "pub"         pub struct Pub          /// `pub`
627    "ref"         pub struct Ref          /// `ref`
628    "return"      pub struct Return       /// `return`
629    "Self"        pub struct SelfType     /// `Self`
630    "self"        pub struct SelfValue    /// `self`
631    "static"      pub struct Static       /// `static`
632    "struct"      pub struct Struct       /// `struct`
633    "super"       pub struct Super        /// `super`
634    "trait"       pub struct Trait        /// `trait`
635    "try"         pub struct Try          /// `try`
636    "type"        pub struct Type         /// `type`
637    "typeof"      pub struct Typeof       /// `typeof`
638    "union"       pub struct Union        /// `union`
639    "unsafe"      pub struct Unsafe       /// `unsafe`
640    "unsized"     pub struct Unsized      /// `unsized`
641    "use"         pub struct Use          /// `use`
642    "virtual"     pub struct Virtual      /// `virtual`
643    "where"       pub struct Where        /// `where`
644    "while"       pub struct While        /// `while`
645    "yield"       pub struct Yield        /// `yield`
646}
647
648define_punctuation! {
649    "+"           pub struct Add/1        /// `+`
650    "+="          pub struct AddEq/2      /// `+=`
651    "&"           pub struct And/1        /// `&`
652    "&&"          pub struct AndAnd/2     /// `&&`
653    "&="          pub struct AndEq/2      /// `&=`
654    "@"           pub struct At/1         /// `@`
655    "!"           pub struct Bang/1       /// `!`
656    "^"           pub struct Caret/1      /// `^`
657    "^="          pub struct CaretEq/2    /// `^=`
658    ":"           pub struct Colon/1      /// `:`
659    "::"          pub struct Colon2/2     /// `::`
660    ","           pub struct Comma/1      /// `,`
661    "/"           pub struct Div/1        /// `/`
662    "/="          pub struct DivEq/2      /// `/=`
663    "$"           pub struct Dollar/1     /// `$`
664    "."           pub struct Dot/1        /// `.`
665    ".."          pub struct Dot2/2       /// `..`
666    "..."         pub struct Dot3/3       /// `...`
667    "..="         pub struct DotDotEq/3   /// `..=`
668    "="           pub struct Eq/1         /// `=`
669    "=="          pub struct EqEq/2       /// `==`
670    ">="          pub struct Ge/2         /// `>=`
671    ">"           pub struct Gt/1         /// `>`
672    "<="          pub struct Le/2         /// `<=`
673    "<"           pub struct Lt/1         /// `<`
674    "*="          pub struct MulEq/2      /// `*=`
675    "!="          pub struct Ne/2         /// `!=`
676    "|"           pub struct Or/1         /// `|`
677    "|="          pub struct OrEq/2       /// `|=`
678    "||"          pub struct OrOr/2       /// `||`
679    "#"           pub struct Pound/1      /// `#`
680    "?"           pub struct Question/1   /// `?`
681    "->"          pub struct RArrow/2     /// `->`
682    "<-"          pub struct LArrow/2     /// `<-`
683    "%"           pub struct Rem/1        /// `%`
684    "%="          pub struct RemEq/2      /// `%=`
685    "=>"          pub struct FatArrow/2   /// `=>`
686    ";"           pub struct Semi/1       /// `;`
687    "<<"          pub struct Shl/2        /// `<<`
688    "<<="         pub struct ShlEq/3      /// `<<=`
689    ">>"          pub struct Shr/2        /// `>>`
690    ">>="         pub struct ShrEq/3      /// `>>=`
691    "*"           pub struct Star/1       /// `*`
692    "-"           pub struct Sub/1        /// `-`
693    "-="          pub struct SubEq/2      /// `-=`
694    "~"           pub struct Tilde/1      /// `~`
695}
696
697define_delimiters! {
698    "{"           pub struct Brace        /// `{...}`
699    "["           pub struct Bracket      /// `[...]`
700    "("           pub struct Paren        /// `(...)`
701    " "           pub struct Group        /// None-delimited group
702}
703
704macro_rules! export_token_macro {
705    ($($await_rule:tt)*) => {
706        /// A type-macro that expands to the name of the Rust type representation of a
707        /// given token.
708        ///
709        /// See the [token module] documentation for details and examples.
710        ///
711        /// [token module]: crate::token
712        // Unfortunate duplication due to a rustdoc bug.
713        // https://github.com/rust-lang/rust/issues/45939
714        #[macro_export]
715        macro_rules! Token {
716            (abstract)    => { $crate::token::Abstract };
717            (as)          => { $crate::token::As };
718            (async)       => { $crate::token::Async };
719            (auto)        => { $crate::token::Auto };
720            $($await_rule => { $crate::token::Await };)*
721            (become)      => { $crate::token::Become };
722            (box)         => { $crate::token::Box };
723            (break)       => { $crate::token::Break };
724            (const)       => { $crate::token::Const };
725            (continue)    => { $crate::token::Continue };
726            (crate)       => { $crate::token::Crate };
727            (default)     => { $crate::token::Default };
728            (do)          => { $crate::token::Do };
729            (dyn)         => { $crate::token::Dyn };
730            (else)        => { $crate::token::Else };
731            (enum)        => { $crate::token::Enum };
732            (extern)      => { $crate::token::Extern };
733            (final)       => { $crate::token::Final };
734            (fn)          => { $crate::token::Fn };
735            (for)         => { $crate::token::For };
736            (if)          => { $crate::token::If };
737            (impl)        => { $crate::token::Impl };
738            (in)          => { $crate::token::In };
739            (let)         => { $crate::token::Let };
740            (loop)        => { $crate::token::Loop };
741            (macro)       => { $crate::token::Macro };
742            (match)       => { $crate::token::Match };
743            (mod)         => { $crate::token::Mod };
744            (move)        => { $crate::token::Move };
745            (mut)         => { $crate::token::Mut };
746            (override)    => { $crate::token::Override };
747            (priv)        => { $crate::token::Priv };
748            (pub)         => { $crate::token::Pub };
749            (ref)         => { $crate::token::Ref };
750            (return)      => { $crate::token::Return };
751            (Self)        => { $crate::token::SelfType };
752            (self)        => { $crate::token::SelfValue };
753            (static)      => { $crate::token::Static };
754            (struct)      => { $crate::token::Struct };
755            (super)       => { $crate::token::Super };
756            (trait)       => { $crate::token::Trait };
757            (try)         => { $crate::token::Try };
758            (type)        => { $crate::token::Type };
759            (typeof)      => { $crate::token::Typeof };
760            (union)       => { $crate::token::Union };
761            (unsafe)      => { $crate::token::Unsafe };
762            (unsized)     => { $crate::token::Unsized };
763            (use)         => { $crate::token::Use };
764            (virtual)     => { $crate::token::Virtual };
765            (where)       => { $crate::token::Where };
766            (while)       => { $crate::token::While };
767            (yield)       => { $crate::token::Yield };
768            (+)           => { $crate::token::Add };
769            (+=)          => { $crate::token::AddEq };
770            (&)           => { $crate::token::And };
771            (&&)          => { $crate::token::AndAnd };
772            (&=)          => { $crate::token::AndEq };
773            (@)           => { $crate::token::At };
774            (!)           => { $crate::token::Bang };
775            (^)           => { $crate::token::Caret };
776            (^=)          => { $crate::token::CaretEq };
777            (:)           => { $crate::token::Colon };
778            (::)          => { $crate::token::Colon2 };
779            (,)           => { $crate::token::Comma };
780            (/)           => { $crate::token::Div };
781            (/=)          => { $crate::token::DivEq };
782            ($)           => { $crate::token::Dollar };
783            (.)           => { $crate::token::Dot };
784            (..)          => { $crate::token::Dot2 };
785            (...)         => { $crate::token::Dot3 };
786            (..=)         => { $crate::token::DotDotEq };
787            (=)           => { $crate::token::Eq };
788            (==)          => { $crate::token::EqEq };
789            (>=)          => { $crate::token::Ge };
790            (>)           => { $crate::token::Gt };
791            (<=)          => { $crate::token::Le };
792            (<)           => { $crate::token::Lt };
793            (*=)          => { $crate::token::MulEq };
794            (!=)          => { $crate::token::Ne };
795            (|)           => { $crate::token::Or };
796            (|=)          => { $crate::token::OrEq };
797            (||)          => { $crate::token::OrOr };
798            (#)           => { $crate::token::Pound };
799            (?)           => { $crate::token::Question };
800            (->)          => { $crate::token::RArrow };
801            (<-)          => { $crate::token::LArrow };
802            (%)           => { $crate::token::Rem };
803            (%=)          => { $crate::token::RemEq };
804            (=>)          => { $crate::token::FatArrow };
805            (;)           => { $crate::token::Semi };
806            (<<)          => { $crate::token::Shl };
807            (<<=)         => { $crate::token::ShlEq };
808            (>>)          => { $crate::token::Shr };
809            (>>=)         => { $crate::token::ShrEq };
810            (*)           => { $crate::token::Star };
811            (-)           => { $crate::token::Sub };
812            (-=)          => { $crate::token::SubEq };
813            (~)           => { $crate::token::Tilde };
814            (_)           => { $crate::token::Underscore };
815        }
816    };
817}
818
819// Old rustc does not permit `await` appearing anywhere in the source file.
820// https://github.com/rust-lang/rust/issues/57919
821// We put the Token![await] rule in a place that is not lexed by old rustc.
822#[cfg(not(syn_omit_await_from_token_macro))]
823include!("await.rs"); // export_token_macro![(await)];
824#[cfg(syn_omit_await_from_token_macro)]
825export_token_macro![];
826
827// Not public API.
828#[doc(hidden)]
829#[cfg(feature = "parsing")]
830pub mod parsing {
831    use proc_macro2::{Spacing, Span};
832
833    use crate::buffer::Cursor;
834    use crate::error::{Error, Result};
835    use crate::parse::ParseStream;
836    use crate::span::FromSpans;
837
838    pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
839        input.step(|cursor| {
840            if let Some((ident, rest)) = cursor.ident() {
841                if ident == token {
842                    return Ok((ident.span(), rest));
843                }
844            }
845            Err(cursor.error(format!("expected `{}`", token)))
846        })
847    }
848
849    pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
850        if let Some((ident, _rest)) = cursor.ident() {
851            ident == token
852        } else {
853            false
854        }
855    }
856
857    pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
858        let mut spans = [input.span(); 3];
859        punct_helper(input, token, &mut spans)?;
860        Ok(S::from_spans(&spans))
861    }
862
863    fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
864        input.step(|cursor| {
865            let mut cursor = *cursor;
866            assert!(token.len() <= spans.len());
867
868            for (i, ch) in token.chars().enumerate() {
869                match cursor.punct() {
870                    Some((punct, rest)) => {
871                        spans[i] = punct.span();
872                        if punct.as_char() != ch {
873                            break;
874                        } else if i == token.len() - 1 {
875                            return Ok(((), rest));
876                        } else if punct.spacing() != Spacing::Joint {
877                            break;
878                        }
879                        cursor = rest;
880                    }
881                    None => break,
882                }
883            }
884
885            Err(Error::new(spans[0], format!("expected `{}`", token)))
886        })
887    }
888
889    pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
890        for (i, ch) in token.chars().enumerate() {
891            match cursor.punct() {
892                Some((punct, rest)) => {
893                    if punct.as_char() != ch {
894                        break;
895                    } else if i == token.len() - 1 {
896                        return true;
897                    } else if punct.spacing() != Spacing::Joint {
898                        break;
899                    }
900                    cursor = rest;
901                }
902                None => break,
903            }
904        }
905        false
906    }
907}
908
909// Not public API.
910#[doc(hidden)]
911#[cfg(feature = "printing")]
912pub mod printing {
913    use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
914    use quote::TokenStreamExt;
915
916    pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
917        assert_eq!(s.len(), spans.len());
918
919        let mut chars = s.chars();
920        let mut spans = spans.iter();
921        let ch = chars.next_back().unwrap();
922        let span = spans.next_back().unwrap();
923        for (ch, span) in chars.zip(spans) {
924            let mut op = Punct::new(ch, Spacing::Joint);
925            op.set_span(*span);
926            tokens.append(op);
927        }
928
929        let mut op = Punct::new(ch, Spacing::Alone);
930        op.set_span(*span);
931        tokens.append(op);
932    }
933
934    pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
935        tokens.append(Ident::new(s, span));
936    }
937
938    pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
939    where
940        F: FnOnce(&mut TokenStream),
941    {
942        let delim = match s {
943            "(" => Delimiter::Parenthesis,
944            "[" => Delimiter::Bracket,
945            "{" => Delimiter::Brace,
946            " " => Delimiter::None,
947            _ => panic!("unknown delimiter: {}", s),
948        };
949        let mut inner = TokenStream::new();
950        f(&mut inner);
951        let mut g = Group::new(delim, inner);
952        g.set_span(span);
953        tokens.append(g);
954    }
955}