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 //! ```edition2018
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 //! ```edition2018
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/0.6/quote/trait.ToTokens.html
89 //! [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
90 
91 use std;
92 #[cfg(feature = "extra-traits")]
93 use std::cmp;
94 #[cfg(feature = "extra-traits")]
95 use std::fmt::{self, Debug};
96 #[cfg(feature = "extra-traits")]
97 use std::hash::{Hash, Hasher};
98 use std::ops::{Deref, DerefMut};
99 
100 #[cfg(feature = "parsing")]
101 use proc_macro2::Delimiter;
102 #[cfg(any(feature = "parsing", feature = "printing"))]
103 use proc_macro2::Ident;
104 use proc_macro2::Span;
105 #[cfg(feature = "printing")]
106 use proc_macro2::TokenStream;
107 #[cfg(feature = "printing")]
108 use quote::{ToTokens, TokenStreamExt};
109 
110 use self::private::WithSpan;
111 #[cfg(feature = "parsing")]
112 use buffer::Cursor;
113 #[cfg(feature = "parsing")]
114 use error::Result;
115 #[cfg(any(feature = "full", feature = "derive"))]
116 #[cfg(feature = "parsing")]
117 use lifetime::Lifetime;
118 #[cfg(any(feature = "full", feature = "derive"))]
119 #[cfg(feature = "parsing")]
120 use lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
121 #[cfg(feature = "parsing")]
122 use lookahead;
123 #[cfg(feature = "parsing")]
124 use parse::{Parse, ParseStream};
125 use span::IntoSpans;
126 
127 /// Marker trait for types that represent single tokens.
128 ///
129 /// This trait is sealed and cannot be implemented for types outside of Syn.
130 #[cfg(feature = "parsing")]
131 pub trait Token: private::Sealed {
132     // Not public API.
133     #[doc(hidden)]
peek(cursor: Cursor) -> bool134     fn peek(cursor: Cursor) -> bool;
135 
136     // Not public API.
137     #[doc(hidden)]
display() -> &'static str138     fn display() -> &'static str;
139 }
140 
141 mod private {
142     use proc_macro2::Span;
143 
144     #[cfg(feature = "parsing")]
145     pub trait Sealed {}
146 
147     /// Support writing `token.span` rather than `token.spans[0]` on tokens that
148     /// hold a single span.
149     #[repr(C)]
150     pub struct WithSpan {
151         pub span: Span,
152     }
153 }
154 
155 #[cfg(feature = "parsing")]
156 impl private::Sealed for Ident {}
157 
158 #[cfg(any(feature = "full", feature = "derive"))]
159 #[cfg(feature = "parsing")]
peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool160 fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
161     use std::cell::Cell;
162     use std::rc::Rc;
163 
164     let scope = Span::call_site();
165     let unexpected = Rc::new(Cell::new(None));
166     let buffer = ::private::new_parse_buffer(scope, cursor, unexpected);
167     peek(&buffer)
168 }
169 
170 #[cfg(any(feature = "full", feature = "derive"))]
171 macro_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"))]
193 impl_token!(Lifetime "lifetime");
194 #[cfg(any(feature = "full", feature = "derive"))]
195 impl_token!(Lit "literal");
196 #[cfg(any(feature = "full", feature = "derive"))]
197 impl_token!(LitStr "string literal");
198 #[cfg(any(feature = "full", feature = "derive"))]
199 impl_token!(LitByteStr "byte string literal");
200 #[cfg(any(feature = "full", feature = "derive"))]
201 impl_token!(LitByte "byte literal");
202 #[cfg(any(feature = "full", feature = "derive"))]
203 impl_token!(LitChar "character literal");
204 #[cfg(any(feature = "full", feature = "derive"))]
205 impl_token!(LitInt "integer literal");
206 #[cfg(any(feature = "full", feature = "derive"))]
207 impl_token!(LitFloat "floating point literal");
208 #[cfg(any(feature = "full", feature = "derive"))]
209 impl_token!(LitBool "boolean literal");
210 
211 // Not public API.
212 #[doc(hidden)]
213 #[cfg(feature = "parsing")]
214 pub trait CustomToken {
peek(cursor: Cursor) -> bool215     fn peek(cursor: Cursor) -> bool;
display() -> &'static str216     fn display() -> &'static str;
217 }
218 
219 #[cfg(feature = "parsing")]
220 impl<T: CustomToken> private::Sealed for T {}
221 
222 #[cfg(feature = "parsing")]
223 impl<T: CustomToken> Token for T {
peek(cursor: Cursor) -> bool224     fn peek(cursor: Cursor) -> bool {
225         <Self as CustomToken>::peek(cursor)
226     }
227 
display() -> &'static str228     fn display() -> &'static str {
229         <Self as CustomToken>::display()
230     }
231 }
232 
233 macro_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 -- use the [`Token!`]
240             /// macro instead.
241             ///
242             /// [`Token!`]: index.html
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 
318 macro_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 
338 macro_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 -- use the [`Token!`]
346             /// macro instead.
347             ///
348             /// [`Token!`]: index.html
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 
396 macro_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 
436 macro_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 
499 define_punctuation_structs! {
500     "_" pub struct Underscore/1 /// `_`
501 }
502 
503 #[cfg(feature = "printing")]
504 impl ToTokens for Underscore {
to_tokens(&self, tokens: &mut TokenStream)505     fn to_tokens(&self, tokens: &mut TokenStream) {
506         tokens.append(Ident::new("_", self.span));
507     }
508 }
509 
510 #[cfg(feature = "parsing")]
511 impl Parse for Underscore {
parse(input: ParseStream) -> Result<Self>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")]
530 impl Token for Underscore {
peek(cursor: Cursor) -> bool531     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 
display() -> &'static str541     fn display() -> &'static str {
542         "`_`"
543     }
544 }
545 
546 #[cfg(feature = "parsing")]
547 impl private::Sealed for Underscore {}
548 
549 #[cfg(feature = "parsing")]
550 impl Token for Paren {
peek(cursor: Cursor) -> bool551     fn peek(cursor: Cursor) -> bool {
552         lookahead::is_delimiter(cursor, Delimiter::Parenthesis)
553     }
554 
display() -> &'static str555     fn display() -> &'static str {
556         "parentheses"
557     }
558 }
559 
560 #[cfg(feature = "parsing")]
561 impl Token for Brace {
peek(cursor: Cursor) -> bool562     fn peek(cursor: Cursor) -> bool {
563         lookahead::is_delimiter(cursor, Delimiter::Brace)
564     }
565 
display() -> &'static str566     fn display() -> &'static str {
567         "curly braces"
568     }
569 }
570 
571 #[cfg(feature = "parsing")]
572 impl Token for Bracket {
peek(cursor: Cursor) -> bool573     fn peek(cursor: Cursor) -> bool {
574         lookahead::is_delimiter(cursor, Delimiter::Bracket)
575     }
576 
display() -> &'static str577     fn display() -> &'static str {
578         "square brackets"
579     }
580 }
581 
582 #[cfg(feature = "parsing")]
583 impl Token for Group {
peek(cursor: Cursor) -> bool584     fn peek(cursor: Cursor) -> bool {
585         lookahead::is_delimiter(cursor, Delimiter::None)
586     }
587 
display() -> &'static str588     fn display() -> &'static str {
589         "invisible group"
590     }
591 }
592 
593 define_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     "become"      pub struct Become       /// `become`
599     "box"         pub struct Box          /// `box`
600     "break"       pub struct Break        /// `break`
601     "const"       pub struct Const        /// `const`
602     "continue"    pub struct Continue     /// `continue`
603     "crate"       pub struct Crate        /// `crate`
604     "default"     pub struct Default      /// `default`
605     "do"          pub struct Do           /// `do`
606     "dyn"         pub struct Dyn          /// `dyn`
607     "else"        pub struct Else         /// `else`
608     "enum"        pub struct Enum         /// `enum`
609     "existential" pub struct Existential  /// `existential`
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 
648 define_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 
697 define_delimiters! {
698     "{"           pub struct Brace        /// `{...}`
699     "["           pub struct Bracket      /// `[...]`
700     "("           pub struct Paren        /// `(...)`
701     " "           pub struct Group        /// None-delimited group
702 }
703 
704 macro_rules! export_token_macro {
705     ($($dollar: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]: token/index.html
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             (become)      => { $crate::token::Become };
721             (box)         => { $crate::token::Box };
722             (break)       => { $crate::token::Break };
723             (const)       => { $crate::token::Const };
724             (continue)    => { $crate::token::Continue };
725             (crate)       => { $crate::token::Crate };
726             (default)     => { $crate::token::Default };
727             (do)          => { $crate::token::Do };
728             (dyn)         => { $crate::token::Dyn };
729             (else)        => { $crate::token::Else };
730             (enum)        => { $crate::token::Enum };
731             (existential) => { $crate::token::Existential };
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::Dot };
783             (..)          => { $crate::token::Dot2 };
784             (...)         => { $crate::token::Dot3 };
785             (..=)         => { $crate::token::DotDotEq };
786             (=)           => { $crate::token::Eq };
787             (==)          => { $crate::token::EqEq };
788             (>=)          => { $crate::token::Ge };
789             (>)           => { $crate::token::Gt };
790             (<=)          => { $crate::token::Le };
791             (<)           => { $crate::token::Lt };
792             (*=)          => { $crate::token::MulEq };
793             (!=)          => { $crate::token::Ne };
794             (|)           => { $crate::token::Or };
795             (|=)          => { $crate::token::OrEq };
796             (||)          => { $crate::token::OrOr };
797             (#)           => { $crate::token::Pound };
798             (?)           => { $crate::token::Question };
799             (->)          => { $crate::token::RArrow };
800             (<-)          => { $crate::token::LArrow };
801             (%)           => { $crate::token::Rem };
802             (%=)          => { $crate::token::RemEq };
803             (=>)          => { $crate::token::FatArrow };
804             (;)           => { $crate::token::Semi };
805             (<<)          => { $crate::token::Shl };
806             (<<=)         => { $crate::token::ShlEq };
807             (>>)          => { $crate::token::Shr };
808             (>>=)         => { $crate::token::ShrEq };
809             (*)           => { $crate::token::Star };
810             (-)           => { $crate::token::Sub };
811             (-=)          => { $crate::token::SubEq };
812             (~)           => { $crate::token::Tilde };
813             (_)           => { $crate::token::Underscore };
814             $($dollar     => { $crate::token::Dollar };)*
815         }
816     };
817 }
818 
819 #[cfg(syn_can_match_trailing_dollar)]
820 export_token_macro![($)];
821 
822 // Old rustc does not support ($) => {...} as a macro rule.
823 #[cfg(not(syn_can_match_trailing_dollar))]
824 export_token_macro![];
825 
826 // Old names. TODO: remove these re-exports in a breaking change.
827 // https://github.com/dtolnay/syn/issues/486
828 #[doc(hidden)]
829 pub use self::SelfType as CapSelf;
830 #[doc(hidden)]
831 pub use self::SelfValue as Self_;
832 
833 // Not public API.
834 #[doc(hidden)]
835 #[cfg(feature = "parsing")]
836 pub mod parsing {
837     use proc_macro2::{Spacing, Span};
838 
839     use buffer::Cursor;
840     use error::{Error, Result};
841     use parse::ParseStream;
842     use span::FromSpans;
843 
keyword(input: ParseStream, token: &str) -> Result<Span>844     pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
845         input.step(|cursor| {
846             if let Some((ident, rest)) = cursor.ident() {
847                 if ident == token {
848                     return Ok((ident.span(), rest));
849                 }
850             }
851             Err(cursor.error(format!("expected `{}`", token)))
852         })
853     }
854 
peek_keyword(cursor: Cursor, token: &str) -> bool855     pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
856         if let Some((ident, _rest)) = cursor.ident() {
857             ident == token
858         } else {
859             false
860         }
861     }
862 
punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S>863     pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
864         let mut spans = [input.cursor().span(); 3];
865         punct_helper(input, token, &mut spans)?;
866         Ok(S::from_spans(&spans))
867     }
868 
punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()>869     fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
870         input.step(|cursor| {
871             let mut cursor = *cursor;
872             assert!(token.len() <= spans.len());
873 
874             for (i, ch) in token.chars().enumerate() {
875                 match cursor.punct() {
876                     Some((punct, rest)) => {
877                         spans[i] = punct.span();
878                         if punct.as_char() != ch {
879                             break;
880                         } else if i == token.len() - 1 {
881                             return Ok(((), rest));
882                         } else if punct.spacing() != Spacing::Joint {
883                             break;
884                         }
885                         cursor = rest;
886                     }
887                     None => break,
888                 }
889             }
890 
891             Err(Error::new(spans[0], format!("expected `{}`", token)))
892         })
893     }
894 
peek_punct(mut cursor: Cursor, token: &str) -> bool895     pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
896         for (i, ch) in token.chars().enumerate() {
897             match cursor.punct() {
898                 Some((punct, rest)) => {
899                     if punct.as_char() != ch {
900                         break;
901                     } else if i == token.len() - 1 {
902                         return true;
903                     } else if punct.spacing() != Spacing::Joint {
904                         break;
905                     }
906                     cursor = rest;
907                 }
908                 None => break,
909             }
910         }
911         false
912     }
913 }
914 
915 // Not public API.
916 #[doc(hidden)]
917 #[cfg(feature = "printing")]
918 pub mod printing {
919     use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
920     use quote::TokenStreamExt;
921 
punct(s: &str, spans: &[Span], tokens: &mut TokenStream)922     pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
923         assert_eq!(s.len(), spans.len());
924 
925         let mut chars = s.chars();
926         let mut spans = spans.iter();
927         let ch = chars.next_back().unwrap();
928         let span = spans.next_back().unwrap();
929         for (ch, span) in chars.zip(spans) {
930             let mut op = Punct::new(ch, Spacing::Joint);
931             op.set_span(*span);
932             tokens.append(op);
933         }
934 
935         let mut op = Punct::new(ch, Spacing::Alone);
936         op.set_span(*span);
937         tokens.append(op);
938     }
939 
keyword(s: &str, span: Span, tokens: &mut TokenStream)940     pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
941         tokens.append(Ident::new(s, span));
942     }
943 
delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream),944     pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
945     where
946         F: FnOnce(&mut TokenStream),
947     {
948         let delim = match s {
949             "(" => Delimiter::Parenthesis,
950             "[" => Delimiter::Bracket,
951             "{" => Delimiter::Brace,
952             " " => Delimiter::None,
953             _ => panic!("unknown delimiter: {}", s),
954         };
955         let mut inner = TokenStream::new();
956         f(&mut inner);
957         let mut g = Group::new(delim, inner);
958         g.set_span(span);
959         tokens.append(g);
960     }
961 }
962