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