syn_pub_items/
token.rs

1//! Tokens representing Rust punctuation, keywords, and delimiters.
2//!
3//! The type names in this module can be difficult to keep straight, so we
4//! prefer to use the [`Token!`] macro instead. This is a type-macro that
5//! expands to the token type of the given token.
6//!
7//! [`Token!`]: ../macro.Token.html
8//!
9//! # Example
10//!
11//! The [`ItemStatic`] syntax tree node is defined like this.
12//!
13//! [`ItemStatic`]: ../struct.ItemStatic.html
14//!
15//! ```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
91use std;
92#[cfg(feature = "extra-traits")]
93use std::cmp;
94#[cfg(feature = "extra-traits")]
95use std::fmt::{self, Debug};
96#[cfg(feature = "extra-traits")]
97use std::hash::{Hash, Hasher};
98use std::ops::{Deref, DerefMut};
99
100#[cfg(feature = "parsing")]
101use proc_macro2::Delimiter;
102#[cfg(any(feature = "parsing", feature = "printing"))]
103use proc_macro2::Ident;
104use proc_macro2::Span;
105#[cfg(feature = "printing")]
106use proc_macro2::TokenStream;
107#[cfg(feature = "printing")]
108use quote::{ToTokens, TokenStreamExt};
109
110use self::private::WithSpan;
111#[cfg(feature = "parsing")]
112use buffer::Cursor;
113#[cfg(feature = "parsing")]
114use error::Result;
115#[cfg(any(feature = "full", feature = "derive"))]
116#[cfg(feature = "parsing")]
117use lifetime::Lifetime;
118#[cfg(any(feature = "full", feature = "derive"))]
119#[cfg(feature = "parsing")]
120use lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
121#[cfg(feature = "parsing")]
122use lookahead;
123#[cfg(feature = "parsing")]
124use parse::{Parse, ParseStream};
125use 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")]
131pub trait Token: private::Sealed {
132    // Not public API.
133    #[doc(hidden)]
134    fn peek(cursor: Cursor) -> bool;
135
136    // Not public API.
137    #[doc(hidden)]
138    fn display() -> &'static str;
139}
140
141mod 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")]
156impl private::Sealed for Ident {}
157
158#[cfg(any(feature = "full", feature = "derive"))]
159#[cfg(feature = "parsing")]
160fn 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"))]
171macro_rules! impl_token {
172    ($name:ident $display:expr) => {
173        #[cfg(feature = "parsing")]
174        impl Token for $name {
175            fn peek(cursor: Cursor) -> bool {
176                fn peek(input: ParseStream) -> bool {
177                    <$name as Parse>::parse(input).is_ok()
178                }
179                peek_impl(cursor, peek)
180            }
181
182            fn display() -> &'static str {
183                $display
184            }
185        }
186
187        #[cfg(feature = "parsing")]
188        impl private::Sealed for $name {}
189    };
190}
191
192#[cfg(any(feature = "full", feature = "derive"))]
193impl_token!(Lifetime "lifetime");
194#[cfg(any(feature = "full", feature = "derive"))]
195impl_token!(Lit "literal");
196#[cfg(any(feature = "full", feature = "derive"))]
197impl_token!(LitStr "string literal");
198#[cfg(any(feature = "full", feature = "derive"))]
199impl_token!(LitByteStr "byte string literal");
200#[cfg(any(feature = "full", feature = "derive"))]
201impl_token!(LitByte "byte literal");
202#[cfg(any(feature = "full", feature = "derive"))]
203impl_token!(LitChar "character literal");
204#[cfg(any(feature = "full", feature = "derive"))]
205impl_token!(LitInt "integer literal");
206#[cfg(any(feature = "full", feature = "derive"))]
207impl_token!(LitFloat "floating point literal");
208#[cfg(any(feature = "full", feature = "derive"))]
209impl_token!(LitBool "boolean literal");
210
211// Not public API.
212#[cfg(feature = "parsing")]
213#[doc(hidden)]
214pub trait CustomKeyword {
215    fn ident() -> &'static str;
216    fn display() -> &'static str;
217}
218
219#[cfg(feature = "parsing")]
220impl<K: CustomKeyword> private::Sealed for K {}
221
222#[cfg(feature = "parsing")]
223impl<K: CustomKeyword> Token for K {
224    fn peek(cursor: Cursor) -> bool {
225        parsing::peek_keyword(cursor, K::ident())
226    }
227
228    fn display() -> &'static str {
229        K::display()
230    }
231}
232
233macro_rules! define_keywords {
234    ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
235        $(
236            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
237            #[$doc]
238            ///
239            /// Don't try to remember the name of this type -- 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
318macro_rules! impl_deref_if_len_is_1 {
319    ($name:ident/1) => {
320        impl Deref for $name {
321            type Target = WithSpan;
322
323            fn deref(&self) -> &Self::Target {
324                unsafe { &*(self as *const Self as *const WithSpan) }
325            }
326        }
327
328        impl DerefMut for $name {
329            fn deref_mut(&mut self) -> &mut Self::Target {
330                unsafe { &mut *(self as *mut Self as *mut WithSpan) }
331            }
332        }
333    };
334
335    ($name:ident/$len:tt) => {};
336}
337
338macro_rules! define_punctuation_structs {
339    ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
340        $(
341            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
342            #[repr(C)]
343            #[$doc]
344            ///
345            /// Don't try to remember the name of this type -- 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
396macro_rules! define_punctuation {
397    ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
398        $(
399            define_punctuation_structs! {
400                $token pub struct $name/$len #[$doc]
401            }
402
403            #[cfg(feature = "printing")]
404            impl ToTokens for $name {
405                fn to_tokens(&self, tokens: &mut TokenStream) {
406                    printing::punct($token, &self.spans, tokens);
407                }
408            }
409
410            #[cfg(feature = "parsing")]
411            impl Parse for $name {
412                fn parse(input: ParseStream) -> Result<Self> {
413                    Ok($name {
414                        spans: parsing::punct(input, $token)?,
415                    })
416                }
417            }
418
419            #[cfg(feature = "parsing")]
420            impl Token for $name {
421                fn peek(cursor: Cursor) -> bool {
422                    parsing::peek_punct(cursor, $token)
423                }
424
425                fn display() -> &'static str {
426                    concat!("`", $token, "`")
427                }
428            }
429
430            #[cfg(feature = "parsing")]
431            impl private::Sealed for $name {}
432        )*
433    };
434}
435
436macro_rules! define_delimiters {
437    ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
438        $(
439            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
440            #[$doc]
441            pub struct $name {
442                pub span: Span,
443            }
444
445            #[doc(hidden)]
446            #[allow(non_snake_case)]
447            pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
448                $name {
449                    span: span.into_spans()[0],
450                }
451            }
452
453            impl std::default::Default for $name {
454                fn default() -> Self {
455                    $name {
456                        span: Span::call_site(),
457                    }
458                }
459            }
460
461            #[cfg(feature = "extra-traits")]
462            impl Debug for $name {
463                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
464                    f.write_str(stringify!($name))
465                }
466            }
467
468            #[cfg(feature = "extra-traits")]
469            impl cmp::Eq for $name {}
470
471            #[cfg(feature = "extra-traits")]
472            impl PartialEq for $name {
473                fn eq(&self, _other: &$name) -> bool {
474                    true
475                }
476            }
477
478            #[cfg(feature = "extra-traits")]
479            impl Hash for $name {
480                fn hash<H: Hasher>(&self, _state: &mut H) {}
481            }
482
483            impl $name {
484                #[cfg(feature = "printing")]
485                pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
486                where
487                    F: FnOnce(&mut TokenStream),
488                {
489                    printing::delim($token, self.span, tokens, f);
490                }
491            }
492
493            #[cfg(feature = "parsing")]
494            impl private::Sealed for $name {}
495        )*
496    };
497}
498
499define_punctuation_structs! {
500    "_" pub struct Underscore/1 /// `_`
501}
502
503#[cfg(feature = "printing")]
504impl ToTokens for Underscore {
505    fn to_tokens(&self, tokens: &mut TokenStream) {
506        tokens.append(Ident::new("_", self.span));
507    }
508}
509
510#[cfg(feature = "parsing")]
511impl Parse for Underscore {
512    fn parse(input: ParseStream) -> Result<Self> {
513        input.step(|cursor| {
514            if let Some((ident, rest)) = cursor.ident() {
515                if ident == "_" {
516                    return Ok((Underscore(ident.span()), rest));
517                }
518            }
519            if let Some((punct, rest)) = cursor.punct() {
520                if punct.as_char() == '_' {
521                    return Ok((Underscore(punct.span()), rest));
522                }
523            }
524            Err(cursor.error("expected `_`"))
525        })
526    }
527}
528
529#[cfg(feature = "parsing")]
530impl Token for Underscore {
531    fn peek(cursor: Cursor) -> bool {
532        if let Some((ident, _rest)) = cursor.ident() {
533            return ident == "_";
534        }
535        if let Some((punct, _rest)) = cursor.punct() {
536            return punct.as_char() == '_';
537        }
538        false
539    }
540
541    fn display() -> &'static str {
542        "`_`"
543    }
544}
545
546#[cfg(feature = "parsing")]
547impl private::Sealed for Underscore {}
548
549#[cfg(feature = "parsing")]
550impl Token for Paren {
551    fn peek(cursor: Cursor) -> bool {
552        lookahead::is_delimiter(cursor, Delimiter::Parenthesis)
553    }
554
555    fn display() -> &'static str {
556        "parentheses"
557    }
558}
559
560#[cfg(feature = "parsing")]
561impl Token for Brace {
562    fn peek(cursor: Cursor) -> bool {
563        lookahead::is_delimiter(cursor, Delimiter::Brace)
564    }
565
566    fn display() -> &'static str {
567        "curly braces"
568    }
569}
570
571#[cfg(feature = "parsing")]
572impl Token for Bracket {
573    fn peek(cursor: Cursor) -> bool {
574        lookahead::is_delimiter(cursor, Delimiter::Bracket)
575    }
576
577    fn display() -> &'static str {
578        "square brackets"
579    }
580}
581
582#[cfg(feature = "parsing")]
583impl Token for Group {
584    fn peek(cursor: Cursor) -> bool {
585        lookahead::is_delimiter(cursor, Delimiter::None)
586    }
587
588    fn display() -> &'static str {
589        "invisible group"
590    }
591}
592
593define_keywords! {
594    "abstract"    pub struct Abstract     /// `abstract`
595    "as"          pub struct As           /// `as`
596    "async"       pub struct Async        /// `async`
597    "auto"        pub struct Auto         /// `auto`
598    "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
648define_punctuation! {
649    "+"           pub struct Add/1        /// `+`
650    "+="          pub struct AddEq/2      /// `+=`
651    "&"           pub struct And/1        /// `&`
652    "&&"          pub struct AndAnd/2     /// `&&`
653    "&="          pub struct AndEq/2      /// `&=`
654    "@"           pub struct At/1         /// `@`
655    "!"           pub struct Bang/1       /// `!`
656    "^"           pub struct Caret/1      /// `^`
657    "^="          pub struct CaretEq/2    /// `^=`
658    ":"           pub struct Colon/1      /// `:`
659    "::"          pub struct Colon2/2     /// `::`
660    ","           pub struct Comma/1      /// `,`
661    "/"           pub struct Div/1        /// `/`
662    "/="          pub struct DivEq/2      /// `/=`
663    "$"           pub struct Dollar/1     /// `$`
664    "."           pub struct Dot/1        /// `.`
665    ".."          pub struct Dot2/2       /// `..`
666    "..."         pub struct Dot3/3       /// `...`
667    "..="         pub struct DotDotEq/3   /// `..=`
668    "="           pub struct Eq/1         /// `=`
669    "=="          pub struct EqEq/2       /// `==`
670    ">="          pub struct Ge/2         /// `>=`
671    ">"           pub struct Gt/1         /// `>`
672    "<="          pub struct Le/2         /// `<=`
673    "<"           pub struct Lt/1         /// `<`
674    "*="          pub struct MulEq/2      /// `*=`
675    "!="          pub struct Ne/2         /// `!=`
676    "|"           pub struct Or/1         /// `|`
677    "|="          pub struct OrEq/2       /// `|=`
678    "||"          pub struct OrOr/2       /// `||`
679    "#"           pub struct Pound/1      /// `#`
680    "?"           pub struct Question/1   /// `?`
681    "->"          pub struct RArrow/2     /// `->`
682    "<-"          pub struct LArrow/2     /// `<-`
683    "%"           pub struct Rem/1        /// `%`
684    "%="          pub struct RemEq/2      /// `%=`
685    "=>"          pub struct FatArrow/2   /// `=>`
686    ";"           pub struct Semi/1       /// `;`
687    "<<"          pub struct Shl/2        /// `<<`
688    "<<="         pub struct ShlEq/3      /// `<<=`
689    ">>"          pub struct Shr/2        /// `>>`
690    ">>="         pub struct ShrEq/3      /// `>>=`
691    "*"           pub struct Star/1       /// `*`
692    "-"           pub struct Sub/1        /// `-`
693    "-="          pub struct SubEq/2      /// `-=`
694    "~"           pub struct Tilde/1      /// `~`
695}
696
697define_delimiters! {
698    "{"           pub struct Brace        /// `{...}`
699    "["           pub struct Bracket      /// `[...]`
700    "("           pub struct Paren        /// `(...)`
701    " "           pub struct Group        /// None-delimited group
702}
703
704/// A type-macro that expands to the name of the Rust type representation of a
705/// given token.
706///
707/// See the [token module] documentation for details and examples.
708///
709/// [token module]: token/index.html
710// Unfortunate duplication due to a rustdoc bug.
711// https://github.com/rust-lang/rust/issues/45939
712#[macro_export]
713#[cfg_attr(rustfmt, rustfmt_skip)]
714macro_rules! Token {
715    (abstract)    => { $crate::token::Abstract };
716    (as)          => { $crate::token::As };
717    (async)       => { $crate::token::Async };
718    (auto)        => { $crate::token::Auto };
719    (become)      => { $crate::token::Become };
720    (box)         => { $crate::token::Box };
721    (break)       => { $crate::token::Break };
722    (const)       => { $crate::token::Const };
723    (continue)    => { $crate::token::Continue };
724    (crate)       => { $crate::token::Crate };
725    (default)     => { $crate::token::Default };
726    (do)          => { $crate::token::Do };
727    (dyn)         => { $crate::token::Dyn };
728    (else)        => { $crate::token::Else };
729    (enum)        => { $crate::token::Enum };
730    (existential) => { $crate::token::Existential };
731    (extern)      => { $crate::token::Extern };
732    (final)       => { $crate::token::Final };
733    (fn)          => { $crate::token::Fn };
734    (for)         => { $crate::token::For };
735    (if)          => { $crate::token::If };
736    (impl)        => { $crate::token::Impl };
737    (in)          => { $crate::token::In };
738    (let)         => { $crate::token::Let };
739    (loop)        => { $crate::token::Loop };
740    (macro)       => { $crate::token::Macro };
741    (match)       => { $crate::token::Match };
742    (mod)         => { $crate::token::Mod };
743    (move)        => { $crate::token::Move };
744    (mut)         => { $crate::token::Mut };
745    (override)    => { $crate::token::Override };
746    (priv)        => { $crate::token::Priv };
747    (pub)         => { $crate::token::Pub };
748    (ref)         => { $crate::token::Ref };
749    (return)      => { $crate::token::Return };
750    (Self)        => { $crate::token::SelfType };
751    (self)        => { $crate::token::SelfValue };
752    (static)      => { $crate::token::Static };
753    (struct)      => { $crate::token::Struct };
754    (super)       => { $crate::token::Super };
755    (trait)       => { $crate::token::Trait };
756    (try)         => { $crate::token::Try };
757    (type)        => { $crate::token::Type };
758    (typeof)      => { $crate::token::Typeof };
759    (union)       => { $crate::token::Union };
760    (unsafe)      => { $crate::token::Unsafe };
761    (unsized)     => { $crate::token::Unsized };
762    (use)         => { $crate::token::Use };
763    (virtual)     => { $crate::token::Virtual };
764    (where)       => { $crate::token::Where };
765    (while)       => { $crate::token::While };
766    (yield)       => { $crate::token::Yield };
767    (+)           => { $crate::token::Add };
768    (+=)          => { $crate::token::AddEq };
769    (&)           => { $crate::token::And };
770    (&&)          => { $crate::token::AndAnd };
771    (&=)          => { $crate::token::AndEq };
772    (@)           => { $crate::token::At };
773    (!)           => { $crate::token::Bang };
774    (^)           => { $crate::token::Caret };
775    (^=)          => { $crate::token::CaretEq };
776    (:)           => { $crate::token::Colon };
777    (::)          => { $crate::token::Colon2 };
778    (,)           => { $crate::token::Comma };
779    (/)           => { $crate::token::Div };
780    (/=)          => { $crate::token::DivEq };
781    (.)           => { $crate::token::Dot };
782    (..)          => { $crate::token::Dot2 };
783    (...)         => { $crate::token::Dot3 };
784    (..=)         => { $crate::token::DotDotEq };
785    (=)           => { $crate::token::Eq };
786    (==)          => { $crate::token::EqEq };
787    (>=)          => { $crate::token::Ge };
788    (>)           => { $crate::token::Gt };
789    (<=)          => { $crate::token::Le };
790    (<)           => { $crate::token::Lt };
791    (*=)          => { $crate::token::MulEq };
792    (!=)          => { $crate::token::Ne };
793    (|)           => { $crate::token::Or };
794    (|=)          => { $crate::token::OrEq };
795    (||)          => { $crate::token::OrOr };
796    (#)           => { $crate::token::Pound };
797    (?)           => { $crate::token::Question };
798    (->)          => { $crate::token::RArrow };
799    (<-)          => { $crate::token::LArrow };
800    (%)           => { $crate::token::Rem };
801    (%=)          => { $crate::token::RemEq };
802    (=>)          => { $crate::token::FatArrow };
803    (;)           => { $crate::token::Semi };
804    (<<)          => { $crate::token::Shl };
805    (<<=)         => { $crate::token::ShlEq };
806    (>>)          => { $crate::token::Shr };
807    (>>=)         => { $crate::token::ShrEq };
808    (*)           => { $crate::token::Star };
809    (-)           => { $crate::token::Sub };
810    (-=)          => { $crate::token::SubEq };
811    (~)           => { $crate::token::Tilde };
812    (_)           => { $crate::token::Underscore };
813}
814
815// Old names. TODO: remove these re-exports in a breaking change.
816// https://github.com/dtolnay/syn/issues/486
817#[doc(hidden)]
818pub use self::SelfType as CapSelf;
819#[doc(hidden)]
820pub use self::SelfValue as Self_;
821
822#[cfg(feature = "parsing")]
823mod parsing {
824    use proc_macro2::{Spacing, Span};
825
826    use buffer::Cursor;
827    use error::{Error, Result};
828    use parse::ParseStream;
829    use span::FromSpans;
830
831    pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
832        input.step(|cursor| {
833            if let Some((ident, rest)) = cursor.ident() {
834                if ident == token {
835                    return Ok((ident.span(), rest));
836                }
837            }
838            Err(cursor.error(format!("expected `{}`", token)))
839        })
840    }
841
842    pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
843        if let Some((ident, _rest)) = cursor.ident() {
844            ident == token
845        } else {
846            false
847        }
848    }
849
850    pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
851        let mut spans = [input.cursor().span(); 3];
852        punct_helper(input, token, &mut spans)?;
853        Ok(S::from_spans(&spans))
854    }
855
856    fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
857        input.step(|cursor| {
858            let mut cursor = *cursor;
859            assert!(token.len() <= spans.len());
860
861            for (i, ch) in token.chars().enumerate() {
862                match cursor.punct() {
863                    Some((punct, rest)) => {
864                        spans[i] = punct.span();
865                        if punct.as_char() != ch {
866                            break;
867                        } else if i == token.len() - 1 {
868                            return Ok(((), rest));
869                        } else if punct.spacing() != Spacing::Joint {
870                            break;
871                        }
872                        cursor = rest;
873                    }
874                    None => break,
875                }
876            }
877
878            Err(Error::new(spans[0], format!("expected `{}`", token)))
879        })
880    }
881
882    pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
883        for (i, ch) in token.chars().enumerate() {
884            match cursor.punct() {
885                Some((punct, rest)) => {
886                    if punct.as_char() != ch {
887                        break;
888                    } else if i == token.len() - 1 {
889                        return true;
890                    } else if punct.spacing() != Spacing::Joint {
891                        break;
892                    }
893                    cursor = rest;
894                }
895                None => break,
896            }
897        }
898        false
899    }
900}
901
902#[cfg(feature = "printing")]
903mod printing {
904    use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
905    use quote::TokenStreamExt;
906
907    pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
908        assert_eq!(s.len(), spans.len());
909
910        let mut chars = s.chars();
911        let mut spans = spans.iter();
912        let ch = chars.next_back().unwrap();
913        let span = spans.next_back().unwrap();
914        for (ch, span) in chars.zip(spans) {
915            let mut op = Punct::new(ch, Spacing::Joint);
916            op.set_span(*span);
917            tokens.append(op);
918        }
919
920        let mut op = Punct::new(ch, Spacing::Alone);
921        op.set_span(*span);
922        tokens.append(op);
923    }
924
925    pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
926        tokens.append(Ident::new(s, span));
927    }
928
929    pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
930    where
931        F: FnOnce(&mut TokenStream),
932    {
933        let delim = match s {
934            "(" => Delimiter::Parenthesis,
935            "[" => Delimiter::Bracket,
936            "{" => Delimiter::Brace,
937            " " => Delimiter::None,
938            _ => panic!("unknown delimiter: {}", s),
939        };
940        let mut inner = TokenStream::new();
941        f(&mut inner);
942        let mut g = Group::new(delim, inner);
943        g.set_span(span);
944        tokens.append(g);
945    }
946}