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