xref: /linux/rust/syn/token.rs (revision 69942c0a8965f311ed7ddf842f160c9cfdcda73a)
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")]
94 pub(crate) use self::private::CustomToken;
95 use self::private::WithSpan;
96 #[cfg(feature = "parsing")]
97 use crate::buffer::Cursor;
98 #[cfg(feature = "parsing")]
99 use crate::error::Result;
100 #[cfg(feature = "parsing")]
101 use crate::lifetime::Lifetime;
102 #[cfg(feature = "parsing")]
103 use crate::parse::{Parse, ParseStream};
104 use crate::span::IntoSpans;
105 use proc_macro2::extra::DelimSpan;
106 use proc_macro2::Span;
107 #[cfg(feature = "printing")]
108 use proc_macro2::TokenStream;
109 #[cfg(any(feature = "parsing", feature = "printing"))]
110 use proc_macro2::{Delimiter, Ident};
111 #[cfg(feature = "parsing")]
112 use proc_macro2::{Literal, Punct, TokenTree};
113 #[cfg(feature = "printing")]
114 use quote::{ToTokens, TokenStreamExt};
115 #[cfg(feature = "extra-traits")]
116 use std::cmp;
117 #[cfg(feature = "extra-traits")]
118 use std::fmt::{self, Debug};
119 #[cfg(feature = "extra-traits")]
120 use std::hash::{Hash, Hasher};
121 use 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")]
127 pub 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 
137 pub(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")]
163 impl private::Sealed for Ident {}
164 
165 macro_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 
183 impl_low_level_token!("punctuation token" Punct punct);
184 impl_low_level_token!("literal" Literal literal);
185 impl_low_level_token!("token" TokenTree token_tree);
186 impl_low_level_token!("group token" proc_macro2::Group any_group);
187 impl_low_level_token!("lifetime" Lifetime lifetime);
188 
189 #[cfg(feature = "parsing")]
190 impl<T: CustomToken> private::Sealed for T {}
191 
192 #[cfg(feature = "parsing")]
193 impl<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 
203 macro_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 
305 macro_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 
325 macro_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 
402 macro_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 
444 macro_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 
523 define_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")))]
529 impl 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")))]
537 impl 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")]
556 impl 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")]
573 impl private::Sealed for Underscore {}
574 
575 /// None-delimited group
576 pub struct Group {
577     pub span: Span,
578 }
579 
580 #[doc(hidden)]
581 #[allow(non_snake_case)]
582 pub fn Group<S: IntoSpans<Span>>(span: S) -> Group {
583     Group {
584         span: span.into_spans(),
585     }
586 }
587 
588 impl 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")))]
598 impl Copy for Group {}
599 
600 #[cfg(feature = "clone-impls")]
601 #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
602 impl 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")))]
610 impl 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")))]
618 impl cmp::Eq for Group {}
619 
620 #[cfg(feature = "extra-traits")]
621 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
622 impl 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")))]
630 impl Hash for Group {
631     fn hash<H: Hasher>(&self, _state: &mut H) {}
632 }
633 
634 impl 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")]
648 impl private::Sealed for Group {}
649 
650 #[cfg(feature = "parsing")]
651 impl 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")]
662 impl 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")]
673 impl 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")]
684 impl 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 
694 define_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 
750 define_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 
799 define_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]
873 macro_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")]
979 pub(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")]
1061 pub(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 }
1099