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