File Index
Files and directories
Sign in
FILE

token.rs

File preview with syntax highlighting.

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