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