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` 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 — 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 — 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 /// `{`…`}` 842fad3a1d3Sopenharmony_ci Bracket pub struct Bracket /// `[`…`]` 843fad3a1d3Sopenharmony_ci Parenthesis pub struct Paren /// `(`…`)` 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, 896fad3a1d3Sopenharmony_ci/// ident: name, 897fad3a1d3Sopenharmony_ci/// semi_token: Token, 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