1fad3a1d3Sopenharmony_ci//! Parsing interface for parsing a token stream into a syntax tree node. 2fad3a1d3Sopenharmony_ci//! 3fad3a1d3Sopenharmony_ci//! Parsing in Syn is built on parser functions that take in a [`ParseStream`] 4fad3a1d3Sopenharmony_ci//! and produce a [`Result<T>`] where `T` is some syntax tree node. Underlying 5fad3a1d3Sopenharmony_ci//! these parser functions is a lower level mechanism built around the 6fad3a1d3Sopenharmony_ci//! [`Cursor`] type. `Cursor` is a cheaply copyable cursor over a range of 7fad3a1d3Sopenharmony_ci//! tokens in a token stream. 8fad3a1d3Sopenharmony_ci//! 9fad3a1d3Sopenharmony_ci//! [`Result<T>`]: Result 10fad3a1d3Sopenharmony_ci//! [`Cursor`]: crate::buffer::Cursor 11fad3a1d3Sopenharmony_ci//! 12fad3a1d3Sopenharmony_ci//! # Example 13fad3a1d3Sopenharmony_ci//! 14fad3a1d3Sopenharmony_ci//! Here is a snippet of parsing code to get a feel for the style of the 15fad3a1d3Sopenharmony_ci//! library. We define data structures for a subset of Rust syntax including 16fad3a1d3Sopenharmony_ci//! enums (not shown) and structs, then provide implementations of the [`Parse`] 17fad3a1d3Sopenharmony_ci//! trait to parse these syntax tree data structures from a token stream. 18fad3a1d3Sopenharmony_ci//! 19fad3a1d3Sopenharmony_ci//! Once `Parse` impls have been defined, they can be called conveniently from a 20fad3a1d3Sopenharmony_ci//! procedural macro through [`parse_macro_input!`] as shown at the bottom of 21fad3a1d3Sopenharmony_ci//! the snippet. If the caller provides syntactically invalid input to the 22fad3a1d3Sopenharmony_ci//! procedural macro, they will receive a helpful compiler error message 23fad3a1d3Sopenharmony_ci//! pointing out the exact token that triggered the failure to parse. 24fad3a1d3Sopenharmony_ci//! 25fad3a1d3Sopenharmony_ci//! [`parse_macro_input!`]: crate::parse_macro_input! 26fad3a1d3Sopenharmony_ci//! 27fad3a1d3Sopenharmony_ci//! ``` 28fad3a1d3Sopenharmony_ci//! # extern crate proc_macro; 29fad3a1d3Sopenharmony_ci//! # 30fad3a1d3Sopenharmony_ci//! use proc_macro::TokenStream; 31fad3a1d3Sopenharmony_ci//! use syn::{braced, parse_macro_input, token, Field, Ident, Result, Token}; 32fad3a1d3Sopenharmony_ci//! use syn::parse::{Parse, ParseStream}; 33fad3a1d3Sopenharmony_ci//! use syn::punctuated::Punctuated; 34fad3a1d3Sopenharmony_ci//! 35fad3a1d3Sopenharmony_ci//! enum Item { 36fad3a1d3Sopenharmony_ci//! Struct(ItemStruct), 37fad3a1d3Sopenharmony_ci//! Enum(ItemEnum), 38fad3a1d3Sopenharmony_ci//! } 39fad3a1d3Sopenharmony_ci//! 40fad3a1d3Sopenharmony_ci//! struct ItemStruct { 41fad3a1d3Sopenharmony_ci//! struct_token: Token![struct], 42fad3a1d3Sopenharmony_ci//! ident: Ident, 43fad3a1d3Sopenharmony_ci//! brace_token: token::Brace, 44fad3a1d3Sopenharmony_ci//! fields: Punctuated<Field, Token![,]>, 45fad3a1d3Sopenharmony_ci//! } 46fad3a1d3Sopenharmony_ci//! # 47fad3a1d3Sopenharmony_ci//! # enum ItemEnum {} 48fad3a1d3Sopenharmony_ci//! 49fad3a1d3Sopenharmony_ci//! impl Parse for Item { 50fad3a1d3Sopenharmony_ci//! fn parse(input: ParseStream) -> Result<Self> { 51fad3a1d3Sopenharmony_ci//! let lookahead = input.lookahead1(); 52fad3a1d3Sopenharmony_ci//! if lookahead.peek(Token![struct]) { 53fad3a1d3Sopenharmony_ci//! input.parse().map(Item::Struct) 54fad3a1d3Sopenharmony_ci//! } else if lookahead.peek(Token![enum]) { 55fad3a1d3Sopenharmony_ci//! input.parse().map(Item::Enum) 56fad3a1d3Sopenharmony_ci//! } else { 57fad3a1d3Sopenharmony_ci//! Err(lookahead.error()) 58fad3a1d3Sopenharmony_ci//! } 59fad3a1d3Sopenharmony_ci//! } 60fad3a1d3Sopenharmony_ci//! } 61fad3a1d3Sopenharmony_ci//! 62fad3a1d3Sopenharmony_ci//! impl Parse for ItemStruct { 63fad3a1d3Sopenharmony_ci//! fn parse(input: ParseStream) -> Result<Self> { 64fad3a1d3Sopenharmony_ci//! let content; 65fad3a1d3Sopenharmony_ci//! Ok(ItemStruct { 66fad3a1d3Sopenharmony_ci//! struct_token: input.parse()?, 67fad3a1d3Sopenharmony_ci//! ident: input.parse()?, 68fad3a1d3Sopenharmony_ci//! brace_token: braced!(content in input), 69fad3a1d3Sopenharmony_ci//! fields: content.parse_terminated(Field::parse_named, Token![,])?, 70fad3a1d3Sopenharmony_ci//! }) 71fad3a1d3Sopenharmony_ci//! } 72fad3a1d3Sopenharmony_ci//! } 73fad3a1d3Sopenharmony_ci//! # 74fad3a1d3Sopenharmony_ci//! # impl Parse for ItemEnum { 75fad3a1d3Sopenharmony_ci//! # fn parse(input: ParseStream) -> Result<Self> { 76fad3a1d3Sopenharmony_ci//! # unimplemented!() 77fad3a1d3Sopenharmony_ci//! # } 78fad3a1d3Sopenharmony_ci//! # } 79fad3a1d3Sopenharmony_ci//! 80fad3a1d3Sopenharmony_ci//! # const IGNORE: &str = stringify! { 81fad3a1d3Sopenharmony_ci//! #[proc_macro] 82fad3a1d3Sopenharmony_ci//! # }; 83fad3a1d3Sopenharmony_ci//! pub fn my_macro(tokens: TokenStream) -> TokenStream { 84fad3a1d3Sopenharmony_ci//! let input = parse_macro_input!(tokens as Item); 85fad3a1d3Sopenharmony_ci//! 86fad3a1d3Sopenharmony_ci//! /* ... */ 87fad3a1d3Sopenharmony_ci//! # TokenStream::new() 88fad3a1d3Sopenharmony_ci//! } 89fad3a1d3Sopenharmony_ci//! ``` 90fad3a1d3Sopenharmony_ci//! 91fad3a1d3Sopenharmony_ci//! # The `syn::parse*` functions 92fad3a1d3Sopenharmony_ci//! 93fad3a1d3Sopenharmony_ci//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve 94fad3a1d3Sopenharmony_ci//! as an entry point for parsing syntax tree nodes that can be parsed in an 95fad3a1d3Sopenharmony_ci//! obvious default way. These functions can return any syntax tree node that 96fad3a1d3Sopenharmony_ci//! implements the [`Parse`] trait, which includes most types in Syn. 97fad3a1d3Sopenharmony_ci//! 98fad3a1d3Sopenharmony_ci//! [`syn::parse`]: crate::parse() 99fad3a1d3Sopenharmony_ci//! [`syn::parse2`]: crate::parse2() 100fad3a1d3Sopenharmony_ci//! [`syn::parse_str`]: crate::parse_str() 101fad3a1d3Sopenharmony_ci//! 102fad3a1d3Sopenharmony_ci//! ``` 103fad3a1d3Sopenharmony_ci//! use syn::Type; 104fad3a1d3Sopenharmony_ci//! 105fad3a1d3Sopenharmony_ci//! # fn run_parser() -> syn::Result<()> { 106fad3a1d3Sopenharmony_ci//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?; 107fad3a1d3Sopenharmony_ci//! # Ok(()) 108fad3a1d3Sopenharmony_ci//! # } 109fad3a1d3Sopenharmony_ci//! # 110fad3a1d3Sopenharmony_ci//! # run_parser().unwrap(); 111fad3a1d3Sopenharmony_ci//! ``` 112fad3a1d3Sopenharmony_ci//! 113fad3a1d3Sopenharmony_ci//! The [`parse_quote!`] macro also uses this approach. 114fad3a1d3Sopenharmony_ci//! 115fad3a1d3Sopenharmony_ci//! [`parse_quote!`]: crate::parse_quote! 116fad3a1d3Sopenharmony_ci//! 117fad3a1d3Sopenharmony_ci//! # The `Parser` trait 118fad3a1d3Sopenharmony_ci//! 119fad3a1d3Sopenharmony_ci//! Some types can be parsed in several ways depending on context. For example 120fad3a1d3Sopenharmony_ci//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like 121fad3a1d3Sopenharmony_ci//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`] 122fad3a1d3Sopenharmony_ci//! may or may not allow trailing punctuation, and parsing it the wrong way 123fad3a1d3Sopenharmony_ci//! would either reject valid input or accept invalid input. 124fad3a1d3Sopenharmony_ci//! 125fad3a1d3Sopenharmony_ci//! [`Attribute`]: crate::Attribute 126fad3a1d3Sopenharmony_ci//! [`Punctuated`]: crate::punctuated 127fad3a1d3Sopenharmony_ci//! 128fad3a1d3Sopenharmony_ci//! The `Parse` trait is not implemented in these cases because there is no good 129fad3a1d3Sopenharmony_ci//! behavior to consider the default. 130fad3a1d3Sopenharmony_ci//! 131fad3a1d3Sopenharmony_ci//! ```compile_fail 132fad3a1d3Sopenharmony_ci//! # extern crate proc_macro; 133fad3a1d3Sopenharmony_ci//! # 134fad3a1d3Sopenharmony_ci//! # use syn::punctuated::Punctuated; 135fad3a1d3Sopenharmony_ci//! # use syn::{PathSegment, Result, Token}; 136fad3a1d3Sopenharmony_ci//! # 137fad3a1d3Sopenharmony_ci//! # fn f(tokens: proc_macro::TokenStream) -> Result<()> { 138fad3a1d3Sopenharmony_ci//! # 139fad3a1d3Sopenharmony_ci//! // Can't parse `Punctuated` without knowing whether trailing punctuation 140fad3a1d3Sopenharmony_ci//! // should be allowed in this context. 141fad3a1d3Sopenharmony_ci//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?; 142fad3a1d3Sopenharmony_ci//! # 143fad3a1d3Sopenharmony_ci//! # Ok(()) 144fad3a1d3Sopenharmony_ci//! # } 145fad3a1d3Sopenharmony_ci//! ``` 146fad3a1d3Sopenharmony_ci//! 147fad3a1d3Sopenharmony_ci//! In these cases the types provide a choice of parser functions rather than a 148fad3a1d3Sopenharmony_ci//! single `Parse` implementation, and those parser functions can be invoked 149fad3a1d3Sopenharmony_ci//! through the [`Parser`] trait. 150fad3a1d3Sopenharmony_ci//! 151fad3a1d3Sopenharmony_ci//! 152fad3a1d3Sopenharmony_ci//! ``` 153fad3a1d3Sopenharmony_ci//! # extern crate proc_macro; 154fad3a1d3Sopenharmony_ci//! # 155fad3a1d3Sopenharmony_ci//! use proc_macro::TokenStream; 156fad3a1d3Sopenharmony_ci//! use syn::parse::Parser; 157fad3a1d3Sopenharmony_ci//! use syn::punctuated::Punctuated; 158fad3a1d3Sopenharmony_ci//! use syn::{Attribute, Expr, PathSegment, Result, Token}; 159fad3a1d3Sopenharmony_ci//! 160fad3a1d3Sopenharmony_ci//! fn call_some_parser_methods(input: TokenStream) -> Result<()> { 161fad3a1d3Sopenharmony_ci//! // Parse a nonempty sequence of path segments separated by `::` punctuation 162fad3a1d3Sopenharmony_ci//! // with no trailing punctuation. 163fad3a1d3Sopenharmony_ci//! let tokens = input.clone(); 164fad3a1d3Sopenharmony_ci//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty; 165fad3a1d3Sopenharmony_ci//! let _path = parser.parse(tokens)?; 166fad3a1d3Sopenharmony_ci//! 167fad3a1d3Sopenharmony_ci//! // Parse a possibly empty sequence of expressions terminated by commas with 168fad3a1d3Sopenharmony_ci//! // an optional trailing punctuation. 169fad3a1d3Sopenharmony_ci//! let tokens = input.clone(); 170fad3a1d3Sopenharmony_ci//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated; 171fad3a1d3Sopenharmony_ci//! let _args = parser.parse(tokens)?; 172fad3a1d3Sopenharmony_ci//! 173fad3a1d3Sopenharmony_ci//! // Parse zero or more outer attributes but not inner attributes. 174fad3a1d3Sopenharmony_ci//! let tokens = input.clone(); 175fad3a1d3Sopenharmony_ci//! let parser = Attribute::parse_outer; 176fad3a1d3Sopenharmony_ci//! let _attrs = parser.parse(tokens)?; 177fad3a1d3Sopenharmony_ci//! 178fad3a1d3Sopenharmony_ci//! Ok(()) 179fad3a1d3Sopenharmony_ci//! } 180fad3a1d3Sopenharmony_ci//! ``` 181fad3a1d3Sopenharmony_ci 182fad3a1d3Sopenharmony_ci#[path = "discouraged.rs"] 183fad3a1d3Sopenharmony_cipub mod discouraged; 184fad3a1d3Sopenharmony_ci 185fad3a1d3Sopenharmony_ciuse crate::buffer::{Cursor, TokenBuffer}; 186fad3a1d3Sopenharmony_ciuse crate::error; 187fad3a1d3Sopenharmony_ciuse crate::lookahead; 188fad3a1d3Sopenharmony_ci#[cfg(feature = "proc-macro")] 189fad3a1d3Sopenharmony_ciuse crate::proc_macro; 190fad3a1d3Sopenharmony_ciuse crate::punctuated::Punctuated; 191fad3a1d3Sopenharmony_ciuse crate::token::Token; 192fad3a1d3Sopenharmony_ciuse proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree}; 193fad3a1d3Sopenharmony_ciuse std::cell::Cell; 194fad3a1d3Sopenharmony_ciuse std::fmt::{self, Debug, Display}; 195fad3a1d3Sopenharmony_ci#[cfg(feature = "extra-traits")] 196fad3a1d3Sopenharmony_ciuse std::hash::{Hash, Hasher}; 197fad3a1d3Sopenharmony_ciuse std::marker::PhantomData; 198fad3a1d3Sopenharmony_ciuse std::mem; 199fad3a1d3Sopenharmony_ciuse std::ops::Deref; 200fad3a1d3Sopenharmony_ciuse std::rc::Rc; 201fad3a1d3Sopenharmony_ciuse std::str::FromStr; 202fad3a1d3Sopenharmony_ci 203fad3a1d3Sopenharmony_cipub use crate::error::{Error, Result}; 204fad3a1d3Sopenharmony_cipub use crate::lookahead::{Lookahead1, Peek}; 205fad3a1d3Sopenharmony_ci 206fad3a1d3Sopenharmony_ci/// Parsing interface implemented by all types that can be parsed in a default 207fad3a1d3Sopenharmony_ci/// way from a token stream. 208fad3a1d3Sopenharmony_ci/// 209fad3a1d3Sopenharmony_ci/// Refer to the [module documentation] for details about implementing and using 210fad3a1d3Sopenharmony_ci/// the `Parse` trait. 211fad3a1d3Sopenharmony_ci/// 212fad3a1d3Sopenharmony_ci/// [module documentation]: self 213fad3a1d3Sopenharmony_cipub trait Parse: Sized { 214fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self>; 215fad3a1d3Sopenharmony_ci} 216fad3a1d3Sopenharmony_ci 217fad3a1d3Sopenharmony_ci/// Input to a Syn parser function. 218fad3a1d3Sopenharmony_ci/// 219fad3a1d3Sopenharmony_ci/// See the methods of this type under the documentation of [`ParseBuffer`]. For 220fad3a1d3Sopenharmony_ci/// an overview of parsing in Syn, refer to the [module documentation]. 221fad3a1d3Sopenharmony_ci/// 222fad3a1d3Sopenharmony_ci/// [module documentation]: self 223fad3a1d3Sopenharmony_cipub type ParseStream<'a> = &'a ParseBuffer<'a>; 224fad3a1d3Sopenharmony_ci 225fad3a1d3Sopenharmony_ci/// Cursor position within a buffered token stream. 226fad3a1d3Sopenharmony_ci/// 227fad3a1d3Sopenharmony_ci/// This type is more commonly used through the type alias [`ParseStream`] which 228fad3a1d3Sopenharmony_ci/// is an alias for `&ParseBuffer`. 229fad3a1d3Sopenharmony_ci/// 230fad3a1d3Sopenharmony_ci/// `ParseStream` is the input type for all parser functions in Syn. They have 231fad3a1d3Sopenharmony_ci/// the signature `fn(ParseStream) -> Result<T>`. 232fad3a1d3Sopenharmony_ci/// 233fad3a1d3Sopenharmony_ci/// ## Calling a parser function 234fad3a1d3Sopenharmony_ci/// 235fad3a1d3Sopenharmony_ci/// There is no public way to construct a `ParseBuffer`. Instead, if you are 236fad3a1d3Sopenharmony_ci/// looking to invoke a parser function that requires `ParseStream` as input, 237fad3a1d3Sopenharmony_ci/// you will need to go through one of the public parsing entry points. 238fad3a1d3Sopenharmony_ci/// 239fad3a1d3Sopenharmony_ci/// - The [`parse_macro_input!`] macro if parsing input of a procedural macro; 240fad3a1d3Sopenharmony_ci/// - One of [the `syn::parse*` functions][syn-parse]; or 241fad3a1d3Sopenharmony_ci/// - A method of the [`Parser`] trait. 242fad3a1d3Sopenharmony_ci/// 243fad3a1d3Sopenharmony_ci/// [`parse_macro_input!`]: crate::parse_macro_input! 244fad3a1d3Sopenharmony_ci/// [syn-parse]: self#the-synparse-functions 245fad3a1d3Sopenharmony_cipub struct ParseBuffer<'a> { 246fad3a1d3Sopenharmony_ci scope: Span, 247fad3a1d3Sopenharmony_ci // Instead of Cell<Cursor<'a>> so that ParseBuffer<'a> is covariant in 'a. 248fad3a1d3Sopenharmony_ci // The rest of the code in this module needs to be careful that only a 249fad3a1d3Sopenharmony_ci // cursor derived from this `cell` is ever assigned to this `cell`. 250fad3a1d3Sopenharmony_ci // 251fad3a1d3Sopenharmony_ci // Cell<Cursor<'a>> cannot be covariant in 'a because then we could take a 252fad3a1d3Sopenharmony_ci // ParseBuffer<'a>, upcast to ParseBuffer<'short> for some lifetime shorter 253fad3a1d3Sopenharmony_ci // than 'a, and then assign a Cursor<'short> into the Cell. 254fad3a1d3Sopenharmony_ci // 255fad3a1d3Sopenharmony_ci // By extension, it would not be safe to expose an API that accepts a 256fad3a1d3Sopenharmony_ci // Cursor<'a> and trusts that it lives as long as the cursor currently in 257fad3a1d3Sopenharmony_ci // the cell. 258fad3a1d3Sopenharmony_ci cell: Cell<Cursor<'static>>, 259fad3a1d3Sopenharmony_ci marker: PhantomData<Cursor<'a>>, 260fad3a1d3Sopenharmony_ci unexpected: Cell<Option<Rc<Cell<Unexpected>>>>, 261fad3a1d3Sopenharmony_ci} 262fad3a1d3Sopenharmony_ci 263fad3a1d3Sopenharmony_ciimpl<'a> Drop for ParseBuffer<'a> { 264fad3a1d3Sopenharmony_ci fn drop(&mut self) { 265fad3a1d3Sopenharmony_ci if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(self.cursor()) { 266fad3a1d3Sopenharmony_ci let (inner, old_span) = inner_unexpected(self); 267fad3a1d3Sopenharmony_ci if old_span.is_none() { 268fad3a1d3Sopenharmony_ci inner.set(Unexpected::Some(unexpected_span)); 269fad3a1d3Sopenharmony_ci } 270fad3a1d3Sopenharmony_ci } 271fad3a1d3Sopenharmony_ci } 272fad3a1d3Sopenharmony_ci} 273fad3a1d3Sopenharmony_ci 274fad3a1d3Sopenharmony_ciimpl<'a> Display for ParseBuffer<'a> { 275fad3a1d3Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 276fad3a1d3Sopenharmony_ci Display::fmt(&self.cursor().token_stream(), f) 277fad3a1d3Sopenharmony_ci } 278fad3a1d3Sopenharmony_ci} 279fad3a1d3Sopenharmony_ci 280fad3a1d3Sopenharmony_ciimpl<'a> Debug for ParseBuffer<'a> { 281fad3a1d3Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 282fad3a1d3Sopenharmony_ci Debug::fmt(&self.cursor().token_stream(), f) 283fad3a1d3Sopenharmony_ci } 284fad3a1d3Sopenharmony_ci} 285fad3a1d3Sopenharmony_ci 286fad3a1d3Sopenharmony_ci/// Cursor state associated with speculative parsing. 287fad3a1d3Sopenharmony_ci/// 288fad3a1d3Sopenharmony_ci/// This type is the input of the closure provided to [`ParseStream::step`]. 289fad3a1d3Sopenharmony_ci/// 290fad3a1d3Sopenharmony_ci/// [`ParseStream::step`]: ParseBuffer::step 291fad3a1d3Sopenharmony_ci/// 292fad3a1d3Sopenharmony_ci/// # Example 293fad3a1d3Sopenharmony_ci/// 294fad3a1d3Sopenharmony_ci/// ``` 295fad3a1d3Sopenharmony_ci/// use proc_macro2::TokenTree; 296fad3a1d3Sopenharmony_ci/// use syn::Result; 297fad3a1d3Sopenharmony_ci/// use syn::parse::ParseStream; 298fad3a1d3Sopenharmony_ci/// 299fad3a1d3Sopenharmony_ci/// // This function advances the stream past the next occurrence of `@`. If 300fad3a1d3Sopenharmony_ci/// // no `@` is present in the stream, the stream position is unchanged and 301fad3a1d3Sopenharmony_ci/// // an error is returned. 302fad3a1d3Sopenharmony_ci/// fn skip_past_next_at(input: ParseStream) -> Result<()> { 303fad3a1d3Sopenharmony_ci/// input.step(|cursor| { 304fad3a1d3Sopenharmony_ci/// let mut rest = *cursor; 305fad3a1d3Sopenharmony_ci/// while let Some((tt, next)) = rest.token_tree() { 306fad3a1d3Sopenharmony_ci/// match &tt { 307fad3a1d3Sopenharmony_ci/// TokenTree::Punct(punct) if punct.as_char() == '@' => { 308fad3a1d3Sopenharmony_ci/// return Ok(((), next)); 309fad3a1d3Sopenharmony_ci/// } 310fad3a1d3Sopenharmony_ci/// _ => rest = next, 311fad3a1d3Sopenharmony_ci/// } 312fad3a1d3Sopenharmony_ci/// } 313fad3a1d3Sopenharmony_ci/// Err(cursor.error("no `@` was found after this point")) 314fad3a1d3Sopenharmony_ci/// }) 315fad3a1d3Sopenharmony_ci/// } 316fad3a1d3Sopenharmony_ci/// # 317fad3a1d3Sopenharmony_ci/// # fn remainder_after_skipping_past_next_at( 318fad3a1d3Sopenharmony_ci/// # input: ParseStream, 319fad3a1d3Sopenharmony_ci/// # ) -> Result<proc_macro2::TokenStream> { 320fad3a1d3Sopenharmony_ci/// # skip_past_next_at(input)?; 321fad3a1d3Sopenharmony_ci/// # input.parse() 322fad3a1d3Sopenharmony_ci/// # } 323fad3a1d3Sopenharmony_ci/// # 324fad3a1d3Sopenharmony_ci/// # use syn::parse::Parser; 325fad3a1d3Sopenharmony_ci/// # let remainder = remainder_after_skipping_past_next_at 326fad3a1d3Sopenharmony_ci/// # .parse_str("a @ b c") 327fad3a1d3Sopenharmony_ci/// # .unwrap(); 328fad3a1d3Sopenharmony_ci/// # assert_eq!(remainder.to_string(), "b c"); 329fad3a1d3Sopenharmony_ci/// ``` 330fad3a1d3Sopenharmony_cipub struct StepCursor<'c, 'a> { 331fad3a1d3Sopenharmony_ci scope: Span, 332fad3a1d3Sopenharmony_ci // This field is covariant in 'c. 333fad3a1d3Sopenharmony_ci cursor: Cursor<'c>, 334fad3a1d3Sopenharmony_ci // This field is contravariant in 'c. Together these make StepCursor 335fad3a1d3Sopenharmony_ci // invariant in 'c. Also covariant in 'a. The user cannot cast 'c to a 336fad3a1d3Sopenharmony_ci // different lifetime but can upcast into a StepCursor with a shorter 337fad3a1d3Sopenharmony_ci // lifetime 'a. 338fad3a1d3Sopenharmony_ci // 339fad3a1d3Sopenharmony_ci // As long as we only ever construct a StepCursor for which 'c outlives 'a, 340fad3a1d3Sopenharmony_ci // this means if ever a StepCursor<'c, 'a> exists we are guaranteed that 'c 341fad3a1d3Sopenharmony_ci // outlives 'a. 342fad3a1d3Sopenharmony_ci marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>, 343fad3a1d3Sopenharmony_ci} 344fad3a1d3Sopenharmony_ci 345fad3a1d3Sopenharmony_ciimpl<'c, 'a> Deref for StepCursor<'c, 'a> { 346fad3a1d3Sopenharmony_ci type Target = Cursor<'c>; 347fad3a1d3Sopenharmony_ci 348fad3a1d3Sopenharmony_ci fn deref(&self) -> &Self::Target { 349fad3a1d3Sopenharmony_ci &self.cursor 350fad3a1d3Sopenharmony_ci } 351fad3a1d3Sopenharmony_ci} 352fad3a1d3Sopenharmony_ci 353fad3a1d3Sopenharmony_ciimpl<'c, 'a> Copy for StepCursor<'c, 'a> {} 354fad3a1d3Sopenharmony_ci 355fad3a1d3Sopenharmony_ciimpl<'c, 'a> Clone for StepCursor<'c, 'a> { 356fad3a1d3Sopenharmony_ci fn clone(&self) -> Self { 357fad3a1d3Sopenharmony_ci *self 358fad3a1d3Sopenharmony_ci } 359fad3a1d3Sopenharmony_ci} 360fad3a1d3Sopenharmony_ci 361fad3a1d3Sopenharmony_ciimpl<'c, 'a> StepCursor<'c, 'a> { 362fad3a1d3Sopenharmony_ci /// Triggers an error at the current position of the parse stream. 363fad3a1d3Sopenharmony_ci /// 364fad3a1d3Sopenharmony_ci /// The `ParseStream::step` invocation will return this same error without 365fad3a1d3Sopenharmony_ci /// advancing the stream state. 366fad3a1d3Sopenharmony_ci pub fn error<T: Display>(self, message: T) -> Error { 367fad3a1d3Sopenharmony_ci error::new_at(self.scope, self.cursor, message) 368fad3a1d3Sopenharmony_ci } 369fad3a1d3Sopenharmony_ci} 370fad3a1d3Sopenharmony_ci 371fad3a1d3Sopenharmony_cipub(crate) fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> { 372fad3a1d3Sopenharmony_ci // Refer to the comments within the StepCursor definition. We use the 373fad3a1d3Sopenharmony_ci // fact that a StepCursor<'c, 'a> exists as proof that 'c outlives 'a. 374fad3a1d3Sopenharmony_ci // Cursor is covariant in its lifetime parameter so we can cast a 375fad3a1d3Sopenharmony_ci // Cursor<'c> to one with the shorter lifetime Cursor<'a>. 376fad3a1d3Sopenharmony_ci let _ = proof; 377fad3a1d3Sopenharmony_ci unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(to) } 378fad3a1d3Sopenharmony_ci} 379fad3a1d3Sopenharmony_ci 380fad3a1d3Sopenharmony_cipub(crate) fn new_parse_buffer( 381fad3a1d3Sopenharmony_ci scope: Span, 382fad3a1d3Sopenharmony_ci cursor: Cursor, 383fad3a1d3Sopenharmony_ci unexpected: Rc<Cell<Unexpected>>, 384fad3a1d3Sopenharmony_ci) -> ParseBuffer { 385fad3a1d3Sopenharmony_ci ParseBuffer { 386fad3a1d3Sopenharmony_ci scope, 387fad3a1d3Sopenharmony_ci // See comment on `cell` in the struct definition. 388fad3a1d3Sopenharmony_ci cell: Cell::new(unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) }), 389fad3a1d3Sopenharmony_ci marker: PhantomData, 390fad3a1d3Sopenharmony_ci unexpected: Cell::new(Some(unexpected)), 391fad3a1d3Sopenharmony_ci } 392fad3a1d3Sopenharmony_ci} 393fad3a1d3Sopenharmony_ci 394fad3a1d3Sopenharmony_cipub(crate) enum Unexpected { 395fad3a1d3Sopenharmony_ci None, 396fad3a1d3Sopenharmony_ci Some(Span), 397fad3a1d3Sopenharmony_ci Chain(Rc<Cell<Unexpected>>), 398fad3a1d3Sopenharmony_ci} 399fad3a1d3Sopenharmony_ci 400fad3a1d3Sopenharmony_ciimpl Default for Unexpected { 401fad3a1d3Sopenharmony_ci fn default() -> Self { 402fad3a1d3Sopenharmony_ci Unexpected::None 403fad3a1d3Sopenharmony_ci } 404fad3a1d3Sopenharmony_ci} 405fad3a1d3Sopenharmony_ci 406fad3a1d3Sopenharmony_ciimpl Clone for Unexpected { 407fad3a1d3Sopenharmony_ci fn clone(&self) -> Self { 408fad3a1d3Sopenharmony_ci match self { 409fad3a1d3Sopenharmony_ci Unexpected::None => Unexpected::None, 410fad3a1d3Sopenharmony_ci Unexpected::Some(span) => Unexpected::Some(*span), 411fad3a1d3Sopenharmony_ci Unexpected::Chain(next) => Unexpected::Chain(next.clone()), 412fad3a1d3Sopenharmony_ci } 413fad3a1d3Sopenharmony_ci } 414fad3a1d3Sopenharmony_ci} 415fad3a1d3Sopenharmony_ci 416fad3a1d3Sopenharmony_ci// We call this on Cell<Unexpected> and Cell<Option<T>> where temporarily 417fad3a1d3Sopenharmony_ci// swapping in a None is cheap. 418fad3a1d3Sopenharmony_cifn cell_clone<T: Default + Clone>(cell: &Cell<T>) -> T { 419fad3a1d3Sopenharmony_ci let prev = cell.take(); 420fad3a1d3Sopenharmony_ci let ret = prev.clone(); 421fad3a1d3Sopenharmony_ci cell.set(prev); 422fad3a1d3Sopenharmony_ci ret 423fad3a1d3Sopenharmony_ci} 424fad3a1d3Sopenharmony_ci 425fad3a1d3Sopenharmony_cifn inner_unexpected(buffer: &ParseBuffer) -> (Rc<Cell<Unexpected>>, Option<Span>) { 426fad3a1d3Sopenharmony_ci let mut unexpected = get_unexpected(buffer); 427fad3a1d3Sopenharmony_ci loop { 428fad3a1d3Sopenharmony_ci match cell_clone(&unexpected) { 429fad3a1d3Sopenharmony_ci Unexpected::None => return (unexpected, None), 430fad3a1d3Sopenharmony_ci Unexpected::Some(span) => return (unexpected, Some(span)), 431fad3a1d3Sopenharmony_ci Unexpected::Chain(next) => unexpected = next, 432fad3a1d3Sopenharmony_ci } 433fad3a1d3Sopenharmony_ci } 434fad3a1d3Sopenharmony_ci} 435fad3a1d3Sopenharmony_ci 436fad3a1d3Sopenharmony_cipub(crate) fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Unexpected>> { 437fad3a1d3Sopenharmony_ci cell_clone(&buffer.unexpected).unwrap() 438fad3a1d3Sopenharmony_ci} 439fad3a1d3Sopenharmony_ci 440fad3a1d3Sopenharmony_cifn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option<Span> { 441fad3a1d3Sopenharmony_ci if cursor.eof() { 442fad3a1d3Sopenharmony_ci return None; 443fad3a1d3Sopenharmony_ci } 444fad3a1d3Sopenharmony_ci while let Some((inner, _span, rest)) = cursor.group(Delimiter::None) { 445fad3a1d3Sopenharmony_ci if let Some(unexpected) = span_of_unexpected_ignoring_nones(inner) { 446fad3a1d3Sopenharmony_ci return Some(unexpected); 447fad3a1d3Sopenharmony_ci } 448fad3a1d3Sopenharmony_ci cursor = rest; 449fad3a1d3Sopenharmony_ci } 450fad3a1d3Sopenharmony_ci if cursor.eof() { 451fad3a1d3Sopenharmony_ci None 452fad3a1d3Sopenharmony_ci } else { 453fad3a1d3Sopenharmony_ci Some(cursor.span()) 454fad3a1d3Sopenharmony_ci } 455fad3a1d3Sopenharmony_ci} 456fad3a1d3Sopenharmony_ci 457fad3a1d3Sopenharmony_ciimpl<'a> ParseBuffer<'a> { 458fad3a1d3Sopenharmony_ci /// Parses a syntax tree node of type `T`, advancing the position of our 459fad3a1d3Sopenharmony_ci /// parse stream past it. 460fad3a1d3Sopenharmony_ci pub fn parse<T: Parse>(&self) -> Result<T> { 461fad3a1d3Sopenharmony_ci T::parse(self) 462fad3a1d3Sopenharmony_ci } 463fad3a1d3Sopenharmony_ci 464fad3a1d3Sopenharmony_ci /// Calls the given parser function to parse a syntax tree node of type `T` 465fad3a1d3Sopenharmony_ci /// from this stream. 466fad3a1d3Sopenharmony_ci /// 467fad3a1d3Sopenharmony_ci /// # Example 468fad3a1d3Sopenharmony_ci /// 469fad3a1d3Sopenharmony_ci /// The parser below invokes [`Attribute::parse_outer`] to parse a vector of 470fad3a1d3Sopenharmony_ci /// zero or more outer attributes. 471fad3a1d3Sopenharmony_ci /// 472fad3a1d3Sopenharmony_ci /// [`Attribute::parse_outer`]: crate::Attribute::parse_outer 473fad3a1d3Sopenharmony_ci /// 474fad3a1d3Sopenharmony_ci /// ``` 475fad3a1d3Sopenharmony_ci /// use syn::{Attribute, Ident, Result, Token}; 476fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 477fad3a1d3Sopenharmony_ci /// 478fad3a1d3Sopenharmony_ci /// // Parses a unit struct with attributes. 479fad3a1d3Sopenharmony_ci /// // 480fad3a1d3Sopenharmony_ci /// // #[path = "s.tmpl"] 481fad3a1d3Sopenharmony_ci /// // struct S; 482fad3a1d3Sopenharmony_ci /// struct UnitStruct { 483fad3a1d3Sopenharmony_ci /// attrs: Vec<Attribute>, 484fad3a1d3Sopenharmony_ci /// struct_token: Token![struct], 485fad3a1d3Sopenharmony_ci /// name: Ident, 486fad3a1d3Sopenharmony_ci /// semi_token: Token![;], 487fad3a1d3Sopenharmony_ci /// } 488fad3a1d3Sopenharmony_ci /// 489fad3a1d3Sopenharmony_ci /// impl Parse for UnitStruct { 490fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 491fad3a1d3Sopenharmony_ci /// Ok(UnitStruct { 492fad3a1d3Sopenharmony_ci /// attrs: input.call(Attribute::parse_outer)?, 493fad3a1d3Sopenharmony_ci /// struct_token: input.parse()?, 494fad3a1d3Sopenharmony_ci /// name: input.parse()?, 495fad3a1d3Sopenharmony_ci /// semi_token: input.parse()?, 496fad3a1d3Sopenharmony_ci /// }) 497fad3a1d3Sopenharmony_ci /// } 498fad3a1d3Sopenharmony_ci /// } 499fad3a1d3Sopenharmony_ci /// ``` 500fad3a1d3Sopenharmony_ci pub fn call<T>(&self, function: fn(ParseStream) -> Result<T>) -> Result<T> { 501fad3a1d3Sopenharmony_ci function(self) 502fad3a1d3Sopenharmony_ci } 503fad3a1d3Sopenharmony_ci 504fad3a1d3Sopenharmony_ci /// Looks at the next token in the parse stream to determine whether it 505fad3a1d3Sopenharmony_ci /// matches the requested type of token. 506fad3a1d3Sopenharmony_ci /// 507fad3a1d3Sopenharmony_ci /// Does not advance the position of the parse stream. 508fad3a1d3Sopenharmony_ci /// 509fad3a1d3Sopenharmony_ci /// # Syntax 510fad3a1d3Sopenharmony_ci /// 511fad3a1d3Sopenharmony_ci /// Note that this method does not use turbofish syntax. Pass the peek type 512fad3a1d3Sopenharmony_ci /// inside of parentheses. 513fad3a1d3Sopenharmony_ci /// 514fad3a1d3Sopenharmony_ci /// - `input.peek(Token![struct])` 515fad3a1d3Sopenharmony_ci /// - `input.peek(Token![==])` 516fad3a1d3Sopenharmony_ci /// - `input.peek(syn::Ident)` *(does not accept keywords)* 517fad3a1d3Sopenharmony_ci /// - `input.peek(syn::Ident::peek_any)` 518fad3a1d3Sopenharmony_ci /// - `input.peek(Lifetime)` 519fad3a1d3Sopenharmony_ci /// - `input.peek(token::Brace)` 520fad3a1d3Sopenharmony_ci /// 521fad3a1d3Sopenharmony_ci /// # Example 522fad3a1d3Sopenharmony_ci /// 523fad3a1d3Sopenharmony_ci /// In this example we finish parsing the list of supertraits when the next 524fad3a1d3Sopenharmony_ci /// token in the input is either `where` or an opening curly brace. 525fad3a1d3Sopenharmony_ci /// 526fad3a1d3Sopenharmony_ci /// ``` 527fad3a1d3Sopenharmony_ci /// use syn::{braced, token, Generics, Ident, Result, Token, TypeParamBound}; 528fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 529fad3a1d3Sopenharmony_ci /// use syn::punctuated::Punctuated; 530fad3a1d3Sopenharmony_ci /// 531fad3a1d3Sopenharmony_ci /// // Parses a trait definition containing no associated items. 532fad3a1d3Sopenharmony_ci /// // 533fad3a1d3Sopenharmony_ci /// // trait Marker<'de, T>: A + B<'de> where Box<T>: Clone {} 534fad3a1d3Sopenharmony_ci /// struct MarkerTrait { 535fad3a1d3Sopenharmony_ci /// trait_token: Token![trait], 536fad3a1d3Sopenharmony_ci /// ident: Ident, 537fad3a1d3Sopenharmony_ci /// generics: Generics, 538fad3a1d3Sopenharmony_ci /// colon_token: Option<Token![:]>, 539fad3a1d3Sopenharmony_ci /// supertraits: Punctuated<TypeParamBound, Token![+]>, 540fad3a1d3Sopenharmony_ci /// brace_token: token::Brace, 541fad3a1d3Sopenharmony_ci /// } 542fad3a1d3Sopenharmony_ci /// 543fad3a1d3Sopenharmony_ci /// impl Parse for MarkerTrait { 544fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 545fad3a1d3Sopenharmony_ci /// let trait_token: Token![trait] = input.parse()?; 546fad3a1d3Sopenharmony_ci /// let ident: Ident = input.parse()?; 547fad3a1d3Sopenharmony_ci /// let mut generics: Generics = input.parse()?; 548fad3a1d3Sopenharmony_ci /// let colon_token: Option<Token![:]> = input.parse()?; 549fad3a1d3Sopenharmony_ci /// 550fad3a1d3Sopenharmony_ci /// let mut supertraits = Punctuated::new(); 551fad3a1d3Sopenharmony_ci /// if colon_token.is_some() { 552fad3a1d3Sopenharmony_ci /// loop { 553fad3a1d3Sopenharmony_ci /// supertraits.push_value(input.parse()?); 554fad3a1d3Sopenharmony_ci /// if input.peek(Token![where]) || input.peek(token::Brace) { 555fad3a1d3Sopenharmony_ci /// break; 556fad3a1d3Sopenharmony_ci /// } 557fad3a1d3Sopenharmony_ci /// supertraits.push_punct(input.parse()?); 558fad3a1d3Sopenharmony_ci /// } 559fad3a1d3Sopenharmony_ci /// } 560fad3a1d3Sopenharmony_ci /// 561fad3a1d3Sopenharmony_ci /// generics.where_clause = input.parse()?; 562fad3a1d3Sopenharmony_ci /// let content; 563fad3a1d3Sopenharmony_ci /// let empty_brace_token = braced!(content in input); 564fad3a1d3Sopenharmony_ci /// 565fad3a1d3Sopenharmony_ci /// Ok(MarkerTrait { 566fad3a1d3Sopenharmony_ci /// trait_token, 567fad3a1d3Sopenharmony_ci /// ident, 568fad3a1d3Sopenharmony_ci /// generics, 569fad3a1d3Sopenharmony_ci /// colon_token, 570fad3a1d3Sopenharmony_ci /// supertraits, 571fad3a1d3Sopenharmony_ci /// brace_token: empty_brace_token, 572fad3a1d3Sopenharmony_ci /// }) 573fad3a1d3Sopenharmony_ci /// } 574fad3a1d3Sopenharmony_ci /// } 575fad3a1d3Sopenharmony_ci /// ``` 576fad3a1d3Sopenharmony_ci pub fn peek<T: Peek>(&self, token: T) -> bool { 577fad3a1d3Sopenharmony_ci let _ = token; 578fad3a1d3Sopenharmony_ci T::Token::peek(self.cursor()) 579fad3a1d3Sopenharmony_ci } 580fad3a1d3Sopenharmony_ci 581fad3a1d3Sopenharmony_ci /// Looks at the second-next token in the parse stream. 582fad3a1d3Sopenharmony_ci /// 583fad3a1d3Sopenharmony_ci /// This is commonly useful as a way to implement contextual keywords. 584fad3a1d3Sopenharmony_ci /// 585fad3a1d3Sopenharmony_ci /// # Example 586fad3a1d3Sopenharmony_ci /// 587fad3a1d3Sopenharmony_ci /// This example needs to use `peek2` because the symbol `union` is not a 588fad3a1d3Sopenharmony_ci /// keyword in Rust. We can't use just `peek` and decide to parse a union if 589fad3a1d3Sopenharmony_ci /// the very next token is `union`, because someone is free to write a `mod 590fad3a1d3Sopenharmony_ci /// union` and a macro invocation that looks like `union::some_macro! { ... 591fad3a1d3Sopenharmony_ci /// }`. In other words `union` is a contextual keyword. 592fad3a1d3Sopenharmony_ci /// 593fad3a1d3Sopenharmony_ci /// ``` 594fad3a1d3Sopenharmony_ci /// use syn::{Ident, ItemUnion, Macro, Result, Token}; 595fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 596fad3a1d3Sopenharmony_ci /// 597fad3a1d3Sopenharmony_ci /// // Parses either a union or a macro invocation. 598fad3a1d3Sopenharmony_ci /// enum UnionOrMacro { 599fad3a1d3Sopenharmony_ci /// // union MaybeUninit<T> { uninit: (), value: T } 600fad3a1d3Sopenharmony_ci /// Union(ItemUnion), 601fad3a1d3Sopenharmony_ci /// // lazy_static! { ... } 602fad3a1d3Sopenharmony_ci /// Macro(Macro), 603fad3a1d3Sopenharmony_ci /// } 604fad3a1d3Sopenharmony_ci /// 605fad3a1d3Sopenharmony_ci /// impl Parse for UnionOrMacro { 606fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 607fad3a1d3Sopenharmony_ci /// if input.peek(Token![union]) && input.peek2(Ident) { 608fad3a1d3Sopenharmony_ci /// input.parse().map(UnionOrMacro::Union) 609fad3a1d3Sopenharmony_ci /// } else { 610fad3a1d3Sopenharmony_ci /// input.parse().map(UnionOrMacro::Macro) 611fad3a1d3Sopenharmony_ci /// } 612fad3a1d3Sopenharmony_ci /// } 613fad3a1d3Sopenharmony_ci /// } 614fad3a1d3Sopenharmony_ci /// ``` 615fad3a1d3Sopenharmony_ci pub fn peek2<T: Peek>(&self, token: T) -> bool { 616fad3a1d3Sopenharmony_ci fn peek2(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool { 617fad3a1d3Sopenharmony_ci if let Some(group) = buffer.cursor().group(Delimiter::None) { 618fad3a1d3Sopenharmony_ci if group.0.skip().map_or(false, peek) { 619fad3a1d3Sopenharmony_ci return true; 620fad3a1d3Sopenharmony_ci } 621fad3a1d3Sopenharmony_ci } 622fad3a1d3Sopenharmony_ci buffer.cursor().skip().map_or(false, peek) 623fad3a1d3Sopenharmony_ci } 624fad3a1d3Sopenharmony_ci 625fad3a1d3Sopenharmony_ci let _ = token; 626fad3a1d3Sopenharmony_ci peek2(self, T::Token::peek) 627fad3a1d3Sopenharmony_ci } 628fad3a1d3Sopenharmony_ci 629fad3a1d3Sopenharmony_ci /// Looks at the third-next token in the parse stream. 630fad3a1d3Sopenharmony_ci pub fn peek3<T: Peek>(&self, token: T) -> bool { 631fad3a1d3Sopenharmony_ci fn peek3(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool { 632fad3a1d3Sopenharmony_ci if let Some(group) = buffer.cursor().group(Delimiter::None) { 633fad3a1d3Sopenharmony_ci if group.0.skip().and_then(Cursor::skip).map_or(false, peek) { 634fad3a1d3Sopenharmony_ci return true; 635fad3a1d3Sopenharmony_ci } 636fad3a1d3Sopenharmony_ci } 637fad3a1d3Sopenharmony_ci buffer 638fad3a1d3Sopenharmony_ci .cursor() 639fad3a1d3Sopenharmony_ci .skip() 640fad3a1d3Sopenharmony_ci .and_then(Cursor::skip) 641fad3a1d3Sopenharmony_ci .map_or(false, peek) 642fad3a1d3Sopenharmony_ci } 643fad3a1d3Sopenharmony_ci 644fad3a1d3Sopenharmony_ci let _ = token; 645fad3a1d3Sopenharmony_ci peek3(self, T::Token::peek) 646fad3a1d3Sopenharmony_ci } 647fad3a1d3Sopenharmony_ci 648fad3a1d3Sopenharmony_ci /// Parses zero or more occurrences of `T` separated by punctuation of type 649fad3a1d3Sopenharmony_ci /// `P`, with optional trailing punctuation. 650fad3a1d3Sopenharmony_ci /// 651fad3a1d3Sopenharmony_ci /// Parsing continues until the end of this parse stream. The entire content 652fad3a1d3Sopenharmony_ci /// of this parse stream must consist of `T` and `P`. 653fad3a1d3Sopenharmony_ci /// 654fad3a1d3Sopenharmony_ci /// # Example 655fad3a1d3Sopenharmony_ci /// 656fad3a1d3Sopenharmony_ci /// ``` 657fad3a1d3Sopenharmony_ci /// # use quote::quote; 658fad3a1d3Sopenharmony_ci /// # 659fad3a1d3Sopenharmony_ci /// use syn::{parenthesized, token, Ident, Result, Token, Type}; 660fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 661fad3a1d3Sopenharmony_ci /// use syn::punctuated::Punctuated; 662fad3a1d3Sopenharmony_ci /// 663fad3a1d3Sopenharmony_ci /// // Parse a simplified tuple struct syntax like: 664fad3a1d3Sopenharmony_ci /// // 665fad3a1d3Sopenharmony_ci /// // struct S(A, B); 666fad3a1d3Sopenharmony_ci /// struct TupleStruct { 667fad3a1d3Sopenharmony_ci /// struct_token: Token![struct], 668fad3a1d3Sopenharmony_ci /// ident: Ident, 669fad3a1d3Sopenharmony_ci /// paren_token: token::Paren, 670fad3a1d3Sopenharmony_ci /// fields: Punctuated<Type, Token![,]>, 671fad3a1d3Sopenharmony_ci /// semi_token: Token![;], 672fad3a1d3Sopenharmony_ci /// } 673fad3a1d3Sopenharmony_ci /// 674fad3a1d3Sopenharmony_ci /// impl Parse for TupleStruct { 675fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 676fad3a1d3Sopenharmony_ci /// let content; 677fad3a1d3Sopenharmony_ci /// Ok(TupleStruct { 678fad3a1d3Sopenharmony_ci /// struct_token: input.parse()?, 679fad3a1d3Sopenharmony_ci /// ident: input.parse()?, 680fad3a1d3Sopenharmony_ci /// paren_token: parenthesized!(content in input), 681fad3a1d3Sopenharmony_ci /// fields: content.parse_terminated(Type::parse, Token![,])?, 682fad3a1d3Sopenharmony_ci /// semi_token: input.parse()?, 683fad3a1d3Sopenharmony_ci /// }) 684fad3a1d3Sopenharmony_ci /// } 685fad3a1d3Sopenharmony_ci /// } 686fad3a1d3Sopenharmony_ci /// # 687fad3a1d3Sopenharmony_ci /// # let input = quote! { 688fad3a1d3Sopenharmony_ci /// # struct S(A, B); 689fad3a1d3Sopenharmony_ci /// # }; 690fad3a1d3Sopenharmony_ci /// # syn::parse2::<TupleStruct>(input).unwrap(); 691fad3a1d3Sopenharmony_ci /// ``` 692fad3a1d3Sopenharmony_ci /// 693fad3a1d3Sopenharmony_ci /// # See also 694fad3a1d3Sopenharmony_ci /// 695fad3a1d3Sopenharmony_ci /// If your separator is anything more complicated than an invocation of the 696fad3a1d3Sopenharmony_ci /// `Token!` macro, this method won't be applicable and you can instead 697fad3a1d3Sopenharmony_ci /// directly use `Punctuated`'s parser functions: [`parse_terminated`], 698fad3a1d3Sopenharmony_ci /// [`parse_separated_nonempty`] etc. 699fad3a1d3Sopenharmony_ci /// 700fad3a1d3Sopenharmony_ci /// [`parse_terminated`]: Punctuated::parse_terminated 701fad3a1d3Sopenharmony_ci /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty 702fad3a1d3Sopenharmony_ci /// 703fad3a1d3Sopenharmony_ci /// ``` 704fad3a1d3Sopenharmony_ci /// use syn::{custom_keyword, Expr, Result, Token}; 705fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 706fad3a1d3Sopenharmony_ci /// use syn::punctuated::Punctuated; 707fad3a1d3Sopenharmony_ci /// 708fad3a1d3Sopenharmony_ci /// mod kw { 709fad3a1d3Sopenharmony_ci /// syn::custom_keyword!(fin); 710fad3a1d3Sopenharmony_ci /// } 711fad3a1d3Sopenharmony_ci /// 712fad3a1d3Sopenharmony_ci /// struct Fin(kw::fin, Token![;]); 713fad3a1d3Sopenharmony_ci /// 714fad3a1d3Sopenharmony_ci /// impl Parse for Fin { 715fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 716fad3a1d3Sopenharmony_ci /// Ok(Self(input.parse()?, input.parse()?)) 717fad3a1d3Sopenharmony_ci /// } 718fad3a1d3Sopenharmony_ci /// } 719fad3a1d3Sopenharmony_ci /// 720fad3a1d3Sopenharmony_ci /// struct Thing { 721fad3a1d3Sopenharmony_ci /// steps: Punctuated<Expr, Fin>, 722fad3a1d3Sopenharmony_ci /// } 723fad3a1d3Sopenharmony_ci /// 724fad3a1d3Sopenharmony_ci /// impl Parse for Thing { 725fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 726fad3a1d3Sopenharmony_ci /// # if true { 727fad3a1d3Sopenharmony_ci /// Ok(Thing { 728fad3a1d3Sopenharmony_ci /// steps: Punctuated::parse_terminated(input)?, 729fad3a1d3Sopenharmony_ci /// }) 730fad3a1d3Sopenharmony_ci /// # } else { 731fad3a1d3Sopenharmony_ci /// // or equivalently, this means the same thing: 732fad3a1d3Sopenharmony_ci /// # Ok(Thing { 733fad3a1d3Sopenharmony_ci /// steps: input.call(Punctuated::parse_terminated)?, 734fad3a1d3Sopenharmony_ci /// # }) 735fad3a1d3Sopenharmony_ci /// # } 736fad3a1d3Sopenharmony_ci /// } 737fad3a1d3Sopenharmony_ci /// } 738fad3a1d3Sopenharmony_ci /// ``` 739fad3a1d3Sopenharmony_ci pub fn parse_terminated<T, P>( 740fad3a1d3Sopenharmony_ci &self, 741fad3a1d3Sopenharmony_ci parser: fn(ParseStream) -> Result<T>, 742fad3a1d3Sopenharmony_ci separator: P, 743fad3a1d3Sopenharmony_ci ) -> Result<Punctuated<T, P::Token>> 744fad3a1d3Sopenharmony_ci where 745fad3a1d3Sopenharmony_ci P: Peek, 746fad3a1d3Sopenharmony_ci P::Token: Parse, 747fad3a1d3Sopenharmony_ci { 748fad3a1d3Sopenharmony_ci let _ = separator; 749fad3a1d3Sopenharmony_ci Punctuated::parse_terminated_with(self, parser) 750fad3a1d3Sopenharmony_ci } 751fad3a1d3Sopenharmony_ci 752fad3a1d3Sopenharmony_ci /// Returns whether there are tokens remaining in this stream. 753fad3a1d3Sopenharmony_ci /// 754fad3a1d3Sopenharmony_ci /// This method returns true at the end of the content of a set of 755fad3a1d3Sopenharmony_ci /// delimiters, as well as at the very end of the complete macro input. 756fad3a1d3Sopenharmony_ci /// 757fad3a1d3Sopenharmony_ci /// # Example 758fad3a1d3Sopenharmony_ci /// 759fad3a1d3Sopenharmony_ci /// ``` 760fad3a1d3Sopenharmony_ci /// use syn::{braced, token, Ident, Item, Result, Token}; 761fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 762fad3a1d3Sopenharmony_ci /// 763fad3a1d3Sopenharmony_ci /// // Parses a Rust `mod m { ... }` containing zero or more items. 764fad3a1d3Sopenharmony_ci /// struct Mod { 765fad3a1d3Sopenharmony_ci /// mod_token: Token![mod], 766fad3a1d3Sopenharmony_ci /// name: Ident, 767fad3a1d3Sopenharmony_ci /// brace_token: token::Brace, 768fad3a1d3Sopenharmony_ci /// items: Vec<Item>, 769fad3a1d3Sopenharmony_ci /// } 770fad3a1d3Sopenharmony_ci /// 771fad3a1d3Sopenharmony_ci /// impl Parse for Mod { 772fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 773fad3a1d3Sopenharmony_ci /// let content; 774fad3a1d3Sopenharmony_ci /// Ok(Mod { 775fad3a1d3Sopenharmony_ci /// mod_token: input.parse()?, 776fad3a1d3Sopenharmony_ci /// name: input.parse()?, 777fad3a1d3Sopenharmony_ci /// brace_token: braced!(content in input), 778fad3a1d3Sopenharmony_ci /// items: { 779fad3a1d3Sopenharmony_ci /// let mut items = Vec::new(); 780fad3a1d3Sopenharmony_ci /// while !content.is_empty() { 781fad3a1d3Sopenharmony_ci /// items.push(content.parse()?); 782fad3a1d3Sopenharmony_ci /// } 783fad3a1d3Sopenharmony_ci /// items 784fad3a1d3Sopenharmony_ci /// }, 785fad3a1d3Sopenharmony_ci /// }) 786fad3a1d3Sopenharmony_ci /// } 787fad3a1d3Sopenharmony_ci /// } 788fad3a1d3Sopenharmony_ci /// ``` 789fad3a1d3Sopenharmony_ci pub fn is_empty(&self) -> bool { 790fad3a1d3Sopenharmony_ci self.cursor().eof() 791fad3a1d3Sopenharmony_ci } 792fad3a1d3Sopenharmony_ci 793fad3a1d3Sopenharmony_ci /// Constructs a helper for peeking at the next token in this stream and 794fad3a1d3Sopenharmony_ci /// building an error message if it is not one of a set of expected tokens. 795fad3a1d3Sopenharmony_ci /// 796fad3a1d3Sopenharmony_ci /// # Example 797fad3a1d3Sopenharmony_ci /// 798fad3a1d3Sopenharmony_ci /// ``` 799fad3a1d3Sopenharmony_ci /// use syn::{ConstParam, Ident, Lifetime, LifetimeParam, Result, Token, TypeParam}; 800fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 801fad3a1d3Sopenharmony_ci /// 802fad3a1d3Sopenharmony_ci /// // A generic parameter, a single one of the comma-separated elements inside 803fad3a1d3Sopenharmony_ci /// // angle brackets in: 804fad3a1d3Sopenharmony_ci /// // 805fad3a1d3Sopenharmony_ci /// // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... } 806fad3a1d3Sopenharmony_ci /// // 807fad3a1d3Sopenharmony_ci /// // On invalid input, lookahead gives us a reasonable error message. 808fad3a1d3Sopenharmony_ci /// // 809fad3a1d3Sopenharmony_ci /// // error: expected one of: identifier, lifetime, `const` 810fad3a1d3Sopenharmony_ci /// // | 811fad3a1d3Sopenharmony_ci /// // 5 | fn f<!Sized>() {} 812fad3a1d3Sopenharmony_ci /// // | ^ 813fad3a1d3Sopenharmony_ci /// enum GenericParam { 814fad3a1d3Sopenharmony_ci /// Type(TypeParam), 815fad3a1d3Sopenharmony_ci /// Lifetime(LifetimeParam), 816fad3a1d3Sopenharmony_ci /// Const(ConstParam), 817fad3a1d3Sopenharmony_ci /// } 818fad3a1d3Sopenharmony_ci /// 819fad3a1d3Sopenharmony_ci /// impl Parse for GenericParam { 820fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 821fad3a1d3Sopenharmony_ci /// let lookahead = input.lookahead1(); 822fad3a1d3Sopenharmony_ci /// if lookahead.peek(Ident) { 823fad3a1d3Sopenharmony_ci /// input.parse().map(GenericParam::Type) 824fad3a1d3Sopenharmony_ci /// } else if lookahead.peek(Lifetime) { 825fad3a1d3Sopenharmony_ci /// input.parse().map(GenericParam::Lifetime) 826fad3a1d3Sopenharmony_ci /// } else if lookahead.peek(Token![const]) { 827fad3a1d3Sopenharmony_ci /// input.parse().map(GenericParam::Const) 828fad3a1d3Sopenharmony_ci /// } else { 829fad3a1d3Sopenharmony_ci /// Err(lookahead.error()) 830fad3a1d3Sopenharmony_ci /// } 831fad3a1d3Sopenharmony_ci /// } 832fad3a1d3Sopenharmony_ci /// } 833fad3a1d3Sopenharmony_ci /// ``` 834fad3a1d3Sopenharmony_ci pub fn lookahead1(&self) -> Lookahead1<'a> { 835fad3a1d3Sopenharmony_ci lookahead::new(self.scope, self.cursor()) 836fad3a1d3Sopenharmony_ci } 837fad3a1d3Sopenharmony_ci 838fad3a1d3Sopenharmony_ci /// Forks a parse stream so that parsing tokens out of either the original 839fad3a1d3Sopenharmony_ci /// or the fork does not advance the position of the other. 840fad3a1d3Sopenharmony_ci /// 841fad3a1d3Sopenharmony_ci /// # Performance 842fad3a1d3Sopenharmony_ci /// 843fad3a1d3Sopenharmony_ci /// Forking a parse stream is a cheap fixed amount of work and does not 844fad3a1d3Sopenharmony_ci /// involve copying token buffers. Where you might hit performance problems 845fad3a1d3Sopenharmony_ci /// is if your macro ends up parsing a large amount of content more than 846fad3a1d3Sopenharmony_ci /// once. 847fad3a1d3Sopenharmony_ci /// 848fad3a1d3Sopenharmony_ci /// ``` 849fad3a1d3Sopenharmony_ci /// # use syn::{Expr, Result}; 850fad3a1d3Sopenharmony_ci /// # use syn::parse::ParseStream; 851fad3a1d3Sopenharmony_ci /// # 852fad3a1d3Sopenharmony_ci /// # fn bad(input: ParseStream) -> Result<Expr> { 853fad3a1d3Sopenharmony_ci /// // Do not do this. 854fad3a1d3Sopenharmony_ci /// if input.fork().parse::<Expr>().is_ok() { 855fad3a1d3Sopenharmony_ci /// return input.parse::<Expr>(); 856fad3a1d3Sopenharmony_ci /// } 857fad3a1d3Sopenharmony_ci /// # unimplemented!() 858fad3a1d3Sopenharmony_ci /// # } 859fad3a1d3Sopenharmony_ci /// ``` 860fad3a1d3Sopenharmony_ci /// 861fad3a1d3Sopenharmony_ci /// As a rule, avoid parsing an unbounded amount of tokens out of a forked 862fad3a1d3Sopenharmony_ci /// parse stream. Only use a fork when the amount of work performed against 863fad3a1d3Sopenharmony_ci /// the fork is small and bounded. 864fad3a1d3Sopenharmony_ci /// 865fad3a1d3Sopenharmony_ci /// When complex speculative parsing against the forked stream is 866fad3a1d3Sopenharmony_ci /// unavoidable, use [`parse::discouraged::Speculative`] to advance the 867fad3a1d3Sopenharmony_ci /// original stream once the fork's parse is determined to have been 868fad3a1d3Sopenharmony_ci /// successful. 869fad3a1d3Sopenharmony_ci /// 870fad3a1d3Sopenharmony_ci /// For a lower level way to perform speculative parsing at the token level, 871fad3a1d3Sopenharmony_ci /// consider using [`ParseStream::step`] instead. 872fad3a1d3Sopenharmony_ci /// 873fad3a1d3Sopenharmony_ci /// [`parse::discouraged::Speculative`]: discouraged::Speculative 874fad3a1d3Sopenharmony_ci /// [`ParseStream::step`]: ParseBuffer::step 875fad3a1d3Sopenharmony_ci /// 876fad3a1d3Sopenharmony_ci /// # Example 877fad3a1d3Sopenharmony_ci /// 878fad3a1d3Sopenharmony_ci /// The parse implementation shown here parses possibly restricted `pub` 879fad3a1d3Sopenharmony_ci /// visibilities. 880fad3a1d3Sopenharmony_ci /// 881fad3a1d3Sopenharmony_ci /// - `pub` 882fad3a1d3Sopenharmony_ci /// - `pub(crate)` 883fad3a1d3Sopenharmony_ci /// - `pub(self)` 884fad3a1d3Sopenharmony_ci /// - `pub(super)` 885fad3a1d3Sopenharmony_ci /// - `pub(in some::path)` 886fad3a1d3Sopenharmony_ci /// 887fad3a1d3Sopenharmony_ci /// To handle the case of visibilities inside of tuple structs, the parser 888fad3a1d3Sopenharmony_ci /// needs to distinguish parentheses that specify visibility restrictions 889fad3a1d3Sopenharmony_ci /// from parentheses that form part of a tuple type. 890fad3a1d3Sopenharmony_ci /// 891fad3a1d3Sopenharmony_ci /// ``` 892fad3a1d3Sopenharmony_ci /// # struct A; 893fad3a1d3Sopenharmony_ci /// # struct B; 894fad3a1d3Sopenharmony_ci /// # struct C; 895fad3a1d3Sopenharmony_ci /// # 896fad3a1d3Sopenharmony_ci /// struct S(pub(crate) A, pub (B, C)); 897fad3a1d3Sopenharmony_ci /// ``` 898fad3a1d3Sopenharmony_ci /// 899fad3a1d3Sopenharmony_ci /// In this example input the first tuple struct element of `S` has 900fad3a1d3Sopenharmony_ci /// `pub(crate)` visibility while the second tuple struct element has `pub` 901fad3a1d3Sopenharmony_ci /// visibility; the parentheses around `(B, C)` are part of the type rather 902fad3a1d3Sopenharmony_ci /// than part of a visibility restriction. 903fad3a1d3Sopenharmony_ci /// 904fad3a1d3Sopenharmony_ci /// The parser uses a forked parse stream to check the first token inside of 905fad3a1d3Sopenharmony_ci /// parentheses after the `pub` keyword. This is a small bounded amount of 906fad3a1d3Sopenharmony_ci /// work performed against the forked parse stream. 907fad3a1d3Sopenharmony_ci /// 908fad3a1d3Sopenharmony_ci /// ``` 909fad3a1d3Sopenharmony_ci /// use syn::{parenthesized, token, Ident, Path, Result, Token}; 910fad3a1d3Sopenharmony_ci /// use syn::ext::IdentExt; 911fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 912fad3a1d3Sopenharmony_ci /// 913fad3a1d3Sopenharmony_ci /// struct PubVisibility { 914fad3a1d3Sopenharmony_ci /// pub_token: Token![pub], 915fad3a1d3Sopenharmony_ci /// restricted: Option<Restricted>, 916fad3a1d3Sopenharmony_ci /// } 917fad3a1d3Sopenharmony_ci /// 918fad3a1d3Sopenharmony_ci /// struct Restricted { 919fad3a1d3Sopenharmony_ci /// paren_token: token::Paren, 920fad3a1d3Sopenharmony_ci /// in_token: Option<Token![in]>, 921fad3a1d3Sopenharmony_ci /// path: Path, 922fad3a1d3Sopenharmony_ci /// } 923fad3a1d3Sopenharmony_ci /// 924fad3a1d3Sopenharmony_ci /// impl Parse for PubVisibility { 925fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 926fad3a1d3Sopenharmony_ci /// let pub_token: Token![pub] = input.parse()?; 927fad3a1d3Sopenharmony_ci /// 928fad3a1d3Sopenharmony_ci /// if input.peek(token::Paren) { 929fad3a1d3Sopenharmony_ci /// let ahead = input.fork(); 930fad3a1d3Sopenharmony_ci /// let mut content; 931fad3a1d3Sopenharmony_ci /// parenthesized!(content in ahead); 932fad3a1d3Sopenharmony_ci /// 933fad3a1d3Sopenharmony_ci /// if content.peek(Token![crate]) 934fad3a1d3Sopenharmony_ci /// || content.peek(Token![self]) 935fad3a1d3Sopenharmony_ci /// || content.peek(Token![super]) 936fad3a1d3Sopenharmony_ci /// { 937fad3a1d3Sopenharmony_ci /// return Ok(PubVisibility { 938fad3a1d3Sopenharmony_ci /// pub_token, 939fad3a1d3Sopenharmony_ci /// restricted: Some(Restricted { 940fad3a1d3Sopenharmony_ci /// paren_token: parenthesized!(content in input), 941fad3a1d3Sopenharmony_ci /// in_token: None, 942fad3a1d3Sopenharmony_ci /// path: Path::from(content.call(Ident::parse_any)?), 943fad3a1d3Sopenharmony_ci /// }), 944fad3a1d3Sopenharmony_ci /// }); 945fad3a1d3Sopenharmony_ci /// } else if content.peek(Token![in]) { 946fad3a1d3Sopenharmony_ci /// return Ok(PubVisibility { 947fad3a1d3Sopenharmony_ci /// pub_token, 948fad3a1d3Sopenharmony_ci /// restricted: Some(Restricted { 949fad3a1d3Sopenharmony_ci /// paren_token: parenthesized!(content in input), 950fad3a1d3Sopenharmony_ci /// in_token: Some(content.parse()?), 951fad3a1d3Sopenharmony_ci /// path: content.call(Path::parse_mod_style)?, 952fad3a1d3Sopenharmony_ci /// }), 953fad3a1d3Sopenharmony_ci /// }); 954fad3a1d3Sopenharmony_ci /// } 955fad3a1d3Sopenharmony_ci /// } 956fad3a1d3Sopenharmony_ci /// 957fad3a1d3Sopenharmony_ci /// Ok(PubVisibility { 958fad3a1d3Sopenharmony_ci /// pub_token, 959fad3a1d3Sopenharmony_ci /// restricted: None, 960fad3a1d3Sopenharmony_ci /// }) 961fad3a1d3Sopenharmony_ci /// } 962fad3a1d3Sopenharmony_ci /// } 963fad3a1d3Sopenharmony_ci /// ``` 964fad3a1d3Sopenharmony_ci pub fn fork(&self) -> Self { 965fad3a1d3Sopenharmony_ci ParseBuffer { 966fad3a1d3Sopenharmony_ci scope: self.scope, 967fad3a1d3Sopenharmony_ci cell: self.cell.clone(), 968fad3a1d3Sopenharmony_ci marker: PhantomData, 969fad3a1d3Sopenharmony_ci // Not the parent's unexpected. Nothing cares whether the clone 970fad3a1d3Sopenharmony_ci // parses all the way unless we `advance_to`. 971fad3a1d3Sopenharmony_ci unexpected: Cell::new(Some(Rc::new(Cell::new(Unexpected::None)))), 972fad3a1d3Sopenharmony_ci } 973fad3a1d3Sopenharmony_ci } 974fad3a1d3Sopenharmony_ci 975fad3a1d3Sopenharmony_ci /// Triggers an error at the current position of the parse stream. 976fad3a1d3Sopenharmony_ci /// 977fad3a1d3Sopenharmony_ci /// # Example 978fad3a1d3Sopenharmony_ci /// 979fad3a1d3Sopenharmony_ci /// ``` 980fad3a1d3Sopenharmony_ci /// use syn::{Expr, Result, Token}; 981fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 982fad3a1d3Sopenharmony_ci /// 983fad3a1d3Sopenharmony_ci /// // Some kind of loop: `while` or `for` or `loop`. 984fad3a1d3Sopenharmony_ci /// struct Loop { 985fad3a1d3Sopenharmony_ci /// expr: Expr, 986fad3a1d3Sopenharmony_ci /// } 987fad3a1d3Sopenharmony_ci /// 988fad3a1d3Sopenharmony_ci /// impl Parse for Loop { 989fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 990fad3a1d3Sopenharmony_ci /// if input.peek(Token![while]) 991fad3a1d3Sopenharmony_ci /// || input.peek(Token![for]) 992fad3a1d3Sopenharmony_ci /// || input.peek(Token![loop]) 993fad3a1d3Sopenharmony_ci /// { 994fad3a1d3Sopenharmony_ci /// Ok(Loop { 995fad3a1d3Sopenharmony_ci /// expr: input.parse()?, 996fad3a1d3Sopenharmony_ci /// }) 997fad3a1d3Sopenharmony_ci /// } else { 998fad3a1d3Sopenharmony_ci /// Err(input.error("expected some kind of loop")) 999fad3a1d3Sopenharmony_ci /// } 1000fad3a1d3Sopenharmony_ci /// } 1001fad3a1d3Sopenharmony_ci /// } 1002fad3a1d3Sopenharmony_ci /// ``` 1003fad3a1d3Sopenharmony_ci pub fn error<T: Display>(&self, message: T) -> Error { 1004fad3a1d3Sopenharmony_ci error::new_at(self.scope, self.cursor(), message) 1005fad3a1d3Sopenharmony_ci } 1006fad3a1d3Sopenharmony_ci 1007fad3a1d3Sopenharmony_ci /// Speculatively parses tokens from this parse stream, advancing the 1008fad3a1d3Sopenharmony_ci /// position of this stream only if parsing succeeds. 1009fad3a1d3Sopenharmony_ci /// 1010fad3a1d3Sopenharmony_ci /// This is a powerful low-level API used for defining the `Parse` impls of 1011fad3a1d3Sopenharmony_ci /// the basic built-in token types. It is not something that will be used 1012fad3a1d3Sopenharmony_ci /// widely outside of the Syn codebase. 1013fad3a1d3Sopenharmony_ci /// 1014fad3a1d3Sopenharmony_ci /// # Example 1015fad3a1d3Sopenharmony_ci /// 1016fad3a1d3Sopenharmony_ci /// ``` 1017fad3a1d3Sopenharmony_ci /// use proc_macro2::TokenTree; 1018fad3a1d3Sopenharmony_ci /// use syn::Result; 1019fad3a1d3Sopenharmony_ci /// use syn::parse::ParseStream; 1020fad3a1d3Sopenharmony_ci /// 1021fad3a1d3Sopenharmony_ci /// // This function advances the stream past the next occurrence of `@`. If 1022fad3a1d3Sopenharmony_ci /// // no `@` is present in the stream, the stream position is unchanged and 1023fad3a1d3Sopenharmony_ci /// // an error is returned. 1024fad3a1d3Sopenharmony_ci /// fn skip_past_next_at(input: ParseStream) -> Result<()> { 1025fad3a1d3Sopenharmony_ci /// input.step(|cursor| { 1026fad3a1d3Sopenharmony_ci /// let mut rest = *cursor; 1027fad3a1d3Sopenharmony_ci /// while let Some((tt, next)) = rest.token_tree() { 1028fad3a1d3Sopenharmony_ci /// match &tt { 1029fad3a1d3Sopenharmony_ci /// TokenTree::Punct(punct) if punct.as_char() == '@' => { 1030fad3a1d3Sopenharmony_ci /// return Ok(((), next)); 1031fad3a1d3Sopenharmony_ci /// } 1032fad3a1d3Sopenharmony_ci /// _ => rest = next, 1033fad3a1d3Sopenharmony_ci /// } 1034fad3a1d3Sopenharmony_ci /// } 1035fad3a1d3Sopenharmony_ci /// Err(cursor.error("no `@` was found after this point")) 1036fad3a1d3Sopenharmony_ci /// }) 1037fad3a1d3Sopenharmony_ci /// } 1038fad3a1d3Sopenharmony_ci /// # 1039fad3a1d3Sopenharmony_ci /// # fn remainder_after_skipping_past_next_at( 1040fad3a1d3Sopenharmony_ci /// # input: ParseStream, 1041fad3a1d3Sopenharmony_ci /// # ) -> Result<proc_macro2::TokenStream> { 1042fad3a1d3Sopenharmony_ci /// # skip_past_next_at(input)?; 1043fad3a1d3Sopenharmony_ci /// # input.parse() 1044fad3a1d3Sopenharmony_ci /// # } 1045fad3a1d3Sopenharmony_ci /// # 1046fad3a1d3Sopenharmony_ci /// # use syn::parse::Parser; 1047fad3a1d3Sopenharmony_ci /// # let remainder = remainder_after_skipping_past_next_at 1048fad3a1d3Sopenharmony_ci /// # .parse_str("a @ b c") 1049fad3a1d3Sopenharmony_ci /// # .unwrap(); 1050fad3a1d3Sopenharmony_ci /// # assert_eq!(remainder.to_string(), "b c"); 1051fad3a1d3Sopenharmony_ci /// ``` 1052fad3a1d3Sopenharmony_ci pub fn step<F, R>(&self, function: F) -> Result<R> 1053fad3a1d3Sopenharmony_ci where 1054fad3a1d3Sopenharmony_ci F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>, 1055fad3a1d3Sopenharmony_ci { 1056fad3a1d3Sopenharmony_ci // Since the user's function is required to work for any 'c, we know 1057fad3a1d3Sopenharmony_ci // that the Cursor<'c> they return is either derived from the input 1058fad3a1d3Sopenharmony_ci // StepCursor<'c, 'a> or from a Cursor<'static>. 1059fad3a1d3Sopenharmony_ci // 1060fad3a1d3Sopenharmony_ci // It would not be legal to write this function without the invariant 1061fad3a1d3Sopenharmony_ci // lifetime 'c in StepCursor<'c, 'a>. If this function were written only 1062fad3a1d3Sopenharmony_ci // in terms of 'a, the user could take our ParseBuffer<'a>, upcast it to 1063fad3a1d3Sopenharmony_ci // a ParseBuffer<'short> which some shorter lifetime than 'a, invoke 1064fad3a1d3Sopenharmony_ci // `step` on their ParseBuffer<'short> with a closure that returns 1065fad3a1d3Sopenharmony_ci // Cursor<'short>, and we would wrongly write that Cursor<'short> into 1066fad3a1d3Sopenharmony_ci // the Cell intended to hold Cursor<'a>. 1067fad3a1d3Sopenharmony_ci // 1068fad3a1d3Sopenharmony_ci // In some cases it may be necessary for R to contain a Cursor<'a>. 1069fad3a1d3Sopenharmony_ci // Within Syn we solve this using `advance_step_cursor` which uses the 1070fad3a1d3Sopenharmony_ci // existence of a StepCursor<'c, 'a> as proof that it is safe to cast 1071fad3a1d3Sopenharmony_ci // from Cursor<'c> to Cursor<'a>. If needed outside of Syn, it would be 1072fad3a1d3Sopenharmony_ci // safe to expose that API as a method on StepCursor. 1073fad3a1d3Sopenharmony_ci let (node, rest) = function(StepCursor { 1074fad3a1d3Sopenharmony_ci scope: self.scope, 1075fad3a1d3Sopenharmony_ci cursor: self.cell.get(), 1076fad3a1d3Sopenharmony_ci marker: PhantomData, 1077fad3a1d3Sopenharmony_ci })?; 1078fad3a1d3Sopenharmony_ci self.cell.set(rest); 1079fad3a1d3Sopenharmony_ci Ok(node) 1080fad3a1d3Sopenharmony_ci } 1081fad3a1d3Sopenharmony_ci 1082fad3a1d3Sopenharmony_ci /// Returns the `Span` of the next token in the parse stream, or 1083fad3a1d3Sopenharmony_ci /// `Span::call_site()` if this parse stream has completely exhausted its 1084fad3a1d3Sopenharmony_ci /// input `TokenStream`. 1085fad3a1d3Sopenharmony_ci pub fn span(&self) -> Span { 1086fad3a1d3Sopenharmony_ci let cursor = self.cursor(); 1087fad3a1d3Sopenharmony_ci if cursor.eof() { 1088fad3a1d3Sopenharmony_ci self.scope 1089fad3a1d3Sopenharmony_ci } else { 1090fad3a1d3Sopenharmony_ci crate::buffer::open_span_of_group(cursor) 1091fad3a1d3Sopenharmony_ci } 1092fad3a1d3Sopenharmony_ci } 1093fad3a1d3Sopenharmony_ci 1094fad3a1d3Sopenharmony_ci /// Provides low-level access to the token representation underlying this 1095fad3a1d3Sopenharmony_ci /// parse stream. 1096fad3a1d3Sopenharmony_ci /// 1097fad3a1d3Sopenharmony_ci /// Cursors are immutable so no operations you perform against the cursor 1098fad3a1d3Sopenharmony_ci /// will affect the state of this parse stream. 1099fad3a1d3Sopenharmony_ci /// 1100fad3a1d3Sopenharmony_ci /// # Example 1101fad3a1d3Sopenharmony_ci /// 1102fad3a1d3Sopenharmony_ci /// ``` 1103fad3a1d3Sopenharmony_ci /// use proc_macro2::TokenStream; 1104fad3a1d3Sopenharmony_ci /// use syn::buffer::Cursor; 1105fad3a1d3Sopenharmony_ci /// use syn::parse::{ParseStream, Result}; 1106fad3a1d3Sopenharmony_ci /// 1107fad3a1d3Sopenharmony_ci /// // Run a parser that returns T, but get its output as TokenStream instead of T. 1108fad3a1d3Sopenharmony_ci /// // This works without T needing to implement ToTokens. 1109fad3a1d3Sopenharmony_ci /// fn recognize_token_stream<T>( 1110fad3a1d3Sopenharmony_ci /// recognizer: fn(ParseStream) -> Result<T>, 1111fad3a1d3Sopenharmony_ci /// ) -> impl Fn(ParseStream) -> Result<TokenStream> { 1112fad3a1d3Sopenharmony_ci /// move |input| { 1113fad3a1d3Sopenharmony_ci /// let begin = input.cursor(); 1114fad3a1d3Sopenharmony_ci /// recognizer(input)?; 1115fad3a1d3Sopenharmony_ci /// let end = input.cursor(); 1116fad3a1d3Sopenharmony_ci /// Ok(tokens_between(begin, end)) 1117fad3a1d3Sopenharmony_ci /// } 1118fad3a1d3Sopenharmony_ci /// } 1119fad3a1d3Sopenharmony_ci /// 1120fad3a1d3Sopenharmony_ci /// // Collect tokens between two cursors as a TokenStream. 1121fad3a1d3Sopenharmony_ci /// fn tokens_between(begin: Cursor, end: Cursor) -> TokenStream { 1122fad3a1d3Sopenharmony_ci /// assert!(begin <= end); 1123fad3a1d3Sopenharmony_ci /// 1124fad3a1d3Sopenharmony_ci /// let mut cursor = begin; 1125fad3a1d3Sopenharmony_ci /// let mut tokens = TokenStream::new(); 1126fad3a1d3Sopenharmony_ci /// while cursor < end { 1127fad3a1d3Sopenharmony_ci /// let (token, next) = cursor.token_tree().unwrap(); 1128fad3a1d3Sopenharmony_ci /// tokens.extend(std::iter::once(token)); 1129fad3a1d3Sopenharmony_ci /// cursor = next; 1130fad3a1d3Sopenharmony_ci /// } 1131fad3a1d3Sopenharmony_ci /// tokens 1132fad3a1d3Sopenharmony_ci /// } 1133fad3a1d3Sopenharmony_ci /// 1134fad3a1d3Sopenharmony_ci /// fn main() { 1135fad3a1d3Sopenharmony_ci /// use quote::quote; 1136fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, Parser}; 1137fad3a1d3Sopenharmony_ci /// use syn::Token; 1138fad3a1d3Sopenharmony_ci /// 1139fad3a1d3Sopenharmony_ci /// // Parse syn::Type as a TokenStream, surrounded by angle brackets. 1140fad3a1d3Sopenharmony_ci /// fn example(input: ParseStream) -> Result<TokenStream> { 1141fad3a1d3Sopenharmony_ci /// let _langle: Token![<] = input.parse()?; 1142fad3a1d3Sopenharmony_ci /// let ty = recognize_token_stream(syn::Type::parse)(input)?; 1143fad3a1d3Sopenharmony_ci /// let _rangle: Token![>] = input.parse()?; 1144fad3a1d3Sopenharmony_ci /// Ok(ty) 1145fad3a1d3Sopenharmony_ci /// } 1146fad3a1d3Sopenharmony_ci /// 1147fad3a1d3Sopenharmony_ci /// let tokens = quote! { <fn() -> u8> }; 1148fad3a1d3Sopenharmony_ci /// println!("{}", example.parse2(tokens).unwrap()); 1149fad3a1d3Sopenharmony_ci /// } 1150fad3a1d3Sopenharmony_ci /// ``` 1151fad3a1d3Sopenharmony_ci pub fn cursor(&self) -> Cursor<'a> { 1152fad3a1d3Sopenharmony_ci self.cell.get() 1153fad3a1d3Sopenharmony_ci } 1154fad3a1d3Sopenharmony_ci 1155fad3a1d3Sopenharmony_ci fn check_unexpected(&self) -> Result<()> { 1156fad3a1d3Sopenharmony_ci match inner_unexpected(self).1 { 1157fad3a1d3Sopenharmony_ci Some(span) => Err(Error::new(span, "unexpected token")), 1158fad3a1d3Sopenharmony_ci None => Ok(()), 1159fad3a1d3Sopenharmony_ci } 1160fad3a1d3Sopenharmony_ci } 1161fad3a1d3Sopenharmony_ci} 1162fad3a1d3Sopenharmony_ci 1163fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1164fad3a1d3Sopenharmony_ciimpl<T: Parse> Parse for Box<T> { 1165fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1166fad3a1d3Sopenharmony_ci input.parse().map(Box::new) 1167fad3a1d3Sopenharmony_ci } 1168fad3a1d3Sopenharmony_ci} 1169fad3a1d3Sopenharmony_ci 1170fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1171fad3a1d3Sopenharmony_ciimpl<T: Parse + Token> Parse for Option<T> { 1172fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1173fad3a1d3Sopenharmony_ci if T::peek(input.cursor()) { 1174fad3a1d3Sopenharmony_ci Ok(Some(input.parse()?)) 1175fad3a1d3Sopenharmony_ci } else { 1176fad3a1d3Sopenharmony_ci Ok(None) 1177fad3a1d3Sopenharmony_ci } 1178fad3a1d3Sopenharmony_ci } 1179fad3a1d3Sopenharmony_ci} 1180fad3a1d3Sopenharmony_ci 1181fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1182fad3a1d3Sopenharmony_ciimpl Parse for TokenStream { 1183fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1184fad3a1d3Sopenharmony_ci input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty()))) 1185fad3a1d3Sopenharmony_ci } 1186fad3a1d3Sopenharmony_ci} 1187fad3a1d3Sopenharmony_ci 1188fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1189fad3a1d3Sopenharmony_ciimpl Parse for TokenTree { 1190fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1191fad3a1d3Sopenharmony_ci input.step(|cursor| match cursor.token_tree() { 1192fad3a1d3Sopenharmony_ci Some((tt, rest)) => Ok((tt, rest)), 1193fad3a1d3Sopenharmony_ci None => Err(cursor.error("expected token tree")), 1194fad3a1d3Sopenharmony_ci }) 1195fad3a1d3Sopenharmony_ci } 1196fad3a1d3Sopenharmony_ci} 1197fad3a1d3Sopenharmony_ci 1198fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1199fad3a1d3Sopenharmony_ciimpl Parse for Group { 1200fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1201fad3a1d3Sopenharmony_ci input.step(|cursor| { 1202fad3a1d3Sopenharmony_ci if let Some((group, rest)) = cursor.any_group_token() { 1203fad3a1d3Sopenharmony_ci if group.delimiter() != Delimiter::None { 1204fad3a1d3Sopenharmony_ci return Ok((group, rest)); 1205fad3a1d3Sopenharmony_ci } 1206fad3a1d3Sopenharmony_ci } 1207fad3a1d3Sopenharmony_ci Err(cursor.error("expected group token")) 1208fad3a1d3Sopenharmony_ci }) 1209fad3a1d3Sopenharmony_ci } 1210fad3a1d3Sopenharmony_ci} 1211fad3a1d3Sopenharmony_ci 1212fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1213fad3a1d3Sopenharmony_ciimpl Parse for Punct { 1214fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1215fad3a1d3Sopenharmony_ci input.step(|cursor| match cursor.punct() { 1216fad3a1d3Sopenharmony_ci Some((punct, rest)) => Ok((punct, rest)), 1217fad3a1d3Sopenharmony_ci None => Err(cursor.error("expected punctuation token")), 1218fad3a1d3Sopenharmony_ci }) 1219fad3a1d3Sopenharmony_ci } 1220fad3a1d3Sopenharmony_ci} 1221fad3a1d3Sopenharmony_ci 1222fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1223fad3a1d3Sopenharmony_ciimpl Parse for Literal { 1224fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 1225fad3a1d3Sopenharmony_ci input.step(|cursor| match cursor.literal() { 1226fad3a1d3Sopenharmony_ci Some((literal, rest)) => Ok((literal, rest)), 1227fad3a1d3Sopenharmony_ci None => Err(cursor.error("expected literal token")), 1228fad3a1d3Sopenharmony_ci }) 1229fad3a1d3Sopenharmony_ci } 1230fad3a1d3Sopenharmony_ci} 1231fad3a1d3Sopenharmony_ci 1232fad3a1d3Sopenharmony_ci/// Parser that can parse Rust tokens into a particular syntax tree node. 1233fad3a1d3Sopenharmony_ci/// 1234fad3a1d3Sopenharmony_ci/// Refer to the [module documentation] for details about parsing in Syn. 1235fad3a1d3Sopenharmony_ci/// 1236fad3a1d3Sopenharmony_ci/// [module documentation]: self 1237fad3a1d3Sopenharmony_cipub trait Parser: Sized { 1238fad3a1d3Sopenharmony_ci type Output; 1239fad3a1d3Sopenharmony_ci 1240fad3a1d3Sopenharmony_ci /// Parse a proc-macro2 token stream into the chosen syntax tree node. 1241fad3a1d3Sopenharmony_ci /// 1242fad3a1d3Sopenharmony_ci /// This function will check that the input is fully parsed. If there are 1243fad3a1d3Sopenharmony_ci /// any unparsed tokens at the end of the stream, an error is returned. 1244fad3a1d3Sopenharmony_ci fn parse2(self, tokens: TokenStream) -> Result<Self::Output>; 1245fad3a1d3Sopenharmony_ci 1246fad3a1d3Sopenharmony_ci /// Parse tokens of source code into the chosen syntax tree node. 1247fad3a1d3Sopenharmony_ci /// 1248fad3a1d3Sopenharmony_ci /// This function will check that the input is fully parsed. If there are 1249fad3a1d3Sopenharmony_ci /// any unparsed tokens at the end of the stream, an error is returned. 1250fad3a1d3Sopenharmony_ci #[cfg(feature = "proc-macro")] 1251fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))] 1252fad3a1d3Sopenharmony_ci fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> { 1253fad3a1d3Sopenharmony_ci self.parse2(proc_macro2::TokenStream::from(tokens)) 1254fad3a1d3Sopenharmony_ci } 1255fad3a1d3Sopenharmony_ci 1256fad3a1d3Sopenharmony_ci /// Parse a string of Rust code into the chosen syntax tree node. 1257fad3a1d3Sopenharmony_ci /// 1258fad3a1d3Sopenharmony_ci /// This function will check that the input is fully parsed. If there are 1259fad3a1d3Sopenharmony_ci /// any unparsed tokens at the end of the string, an error is returned. 1260fad3a1d3Sopenharmony_ci /// 1261fad3a1d3Sopenharmony_ci /// # Hygiene 1262fad3a1d3Sopenharmony_ci /// 1263fad3a1d3Sopenharmony_ci /// Every span in the resulting syntax tree will be set to resolve at the 1264fad3a1d3Sopenharmony_ci /// macro call site. 1265fad3a1d3Sopenharmony_ci fn parse_str(self, s: &str) -> Result<Self::Output> { 1266fad3a1d3Sopenharmony_ci self.parse2(proc_macro2::TokenStream::from_str(s)?) 1267fad3a1d3Sopenharmony_ci } 1268fad3a1d3Sopenharmony_ci 1269fad3a1d3Sopenharmony_ci // Not public API. 1270fad3a1d3Sopenharmony_ci #[doc(hidden)] 1271fad3a1d3Sopenharmony_ci #[cfg(any(feature = "full", feature = "derive"))] 1272fad3a1d3Sopenharmony_ci fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result<Self::Output> { 1273fad3a1d3Sopenharmony_ci let _ = scope; 1274fad3a1d3Sopenharmony_ci self.parse2(tokens) 1275fad3a1d3Sopenharmony_ci } 1276fad3a1d3Sopenharmony_ci} 1277fad3a1d3Sopenharmony_ci 1278fad3a1d3Sopenharmony_cifn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer { 1279fad3a1d3Sopenharmony_ci let scope = Span::call_site(); 1280fad3a1d3Sopenharmony_ci let cursor = tokens.begin(); 1281fad3a1d3Sopenharmony_ci let unexpected = Rc::new(Cell::new(Unexpected::None)); 1282fad3a1d3Sopenharmony_ci new_parse_buffer(scope, cursor, unexpected) 1283fad3a1d3Sopenharmony_ci} 1284fad3a1d3Sopenharmony_ci 1285fad3a1d3Sopenharmony_ciimpl<F, T> Parser for F 1286fad3a1d3Sopenharmony_ciwhere 1287fad3a1d3Sopenharmony_ci F: FnOnce(ParseStream) -> Result<T>, 1288fad3a1d3Sopenharmony_ci{ 1289fad3a1d3Sopenharmony_ci type Output = T; 1290fad3a1d3Sopenharmony_ci 1291fad3a1d3Sopenharmony_ci fn parse2(self, tokens: TokenStream) -> Result<T> { 1292fad3a1d3Sopenharmony_ci let buf = TokenBuffer::new2(tokens); 1293fad3a1d3Sopenharmony_ci let state = tokens_to_parse_buffer(&buf); 1294fad3a1d3Sopenharmony_ci let node = self(&state)?; 1295fad3a1d3Sopenharmony_ci state.check_unexpected()?; 1296fad3a1d3Sopenharmony_ci if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { 1297fad3a1d3Sopenharmony_ci Err(Error::new(unexpected_span, "unexpected token")) 1298fad3a1d3Sopenharmony_ci } else { 1299fad3a1d3Sopenharmony_ci Ok(node) 1300fad3a1d3Sopenharmony_ci } 1301fad3a1d3Sopenharmony_ci } 1302fad3a1d3Sopenharmony_ci 1303fad3a1d3Sopenharmony_ci #[cfg(any(feature = "full", feature = "derive"))] 1304fad3a1d3Sopenharmony_ci fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result<Self::Output> { 1305fad3a1d3Sopenharmony_ci let buf = TokenBuffer::new2(tokens); 1306fad3a1d3Sopenharmony_ci let cursor = buf.begin(); 1307fad3a1d3Sopenharmony_ci let unexpected = Rc::new(Cell::new(Unexpected::None)); 1308fad3a1d3Sopenharmony_ci let state = new_parse_buffer(scope, cursor, unexpected); 1309fad3a1d3Sopenharmony_ci let node = self(&state)?; 1310fad3a1d3Sopenharmony_ci state.check_unexpected()?; 1311fad3a1d3Sopenharmony_ci if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { 1312fad3a1d3Sopenharmony_ci Err(Error::new(unexpected_span, "unexpected token")) 1313fad3a1d3Sopenharmony_ci } else { 1314fad3a1d3Sopenharmony_ci Ok(node) 1315fad3a1d3Sopenharmony_ci } 1316fad3a1d3Sopenharmony_ci } 1317fad3a1d3Sopenharmony_ci} 1318fad3a1d3Sopenharmony_ci 1319fad3a1d3Sopenharmony_ci#[cfg(any(feature = "full", feature = "derive"))] 1320fad3a1d3Sopenharmony_cipub(crate) fn parse_scoped<F: Parser>(f: F, scope: Span, tokens: TokenStream) -> Result<F::Output> { 1321fad3a1d3Sopenharmony_ci f.__parse_scoped(scope, tokens) 1322fad3a1d3Sopenharmony_ci} 1323fad3a1d3Sopenharmony_ci 1324fad3a1d3Sopenharmony_ci/// An empty syntax tree node that consumes no tokens when parsed. 1325fad3a1d3Sopenharmony_ci/// 1326fad3a1d3Sopenharmony_ci/// This is useful for attribute macros that want to ensure they are not 1327fad3a1d3Sopenharmony_ci/// provided any attribute args. 1328fad3a1d3Sopenharmony_ci/// 1329fad3a1d3Sopenharmony_ci/// ``` 1330fad3a1d3Sopenharmony_ci/// # extern crate proc_macro; 1331fad3a1d3Sopenharmony_ci/// # 1332fad3a1d3Sopenharmony_ci/// use proc_macro::TokenStream; 1333fad3a1d3Sopenharmony_ci/// use syn::parse_macro_input; 1334fad3a1d3Sopenharmony_ci/// use syn::parse::Nothing; 1335fad3a1d3Sopenharmony_ci/// 1336fad3a1d3Sopenharmony_ci/// # const IGNORE: &str = stringify! { 1337fad3a1d3Sopenharmony_ci/// #[proc_macro_attribute] 1338fad3a1d3Sopenharmony_ci/// # }; 1339fad3a1d3Sopenharmony_ci/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { 1340fad3a1d3Sopenharmony_ci/// parse_macro_input!(args as Nothing); 1341fad3a1d3Sopenharmony_ci/// 1342fad3a1d3Sopenharmony_ci/// /* ... */ 1343fad3a1d3Sopenharmony_ci/// # TokenStream::new() 1344fad3a1d3Sopenharmony_ci/// } 1345fad3a1d3Sopenharmony_ci/// ``` 1346fad3a1d3Sopenharmony_ci/// 1347fad3a1d3Sopenharmony_ci/// ```text 1348fad3a1d3Sopenharmony_ci/// error: unexpected token 1349fad3a1d3Sopenharmony_ci/// --> src/main.rs:3:19 1350fad3a1d3Sopenharmony_ci/// | 1351fad3a1d3Sopenharmony_ci/// 3 | #[my_attr(asdf)] 1352fad3a1d3Sopenharmony_ci/// | ^^^^ 1353fad3a1d3Sopenharmony_ci/// ``` 1354fad3a1d3Sopenharmony_cipub struct Nothing; 1355fad3a1d3Sopenharmony_ci 1356fad3a1d3Sopenharmony_ciimpl Parse for Nothing { 1357fad3a1d3Sopenharmony_ci fn parse(_input: ParseStream) -> Result<Self> { 1358fad3a1d3Sopenharmony_ci Ok(Nothing) 1359fad3a1d3Sopenharmony_ci } 1360fad3a1d3Sopenharmony_ci} 1361fad3a1d3Sopenharmony_ci 1362fad3a1d3Sopenharmony_ci#[cfg(feature = "extra-traits")] 1363fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 1364fad3a1d3Sopenharmony_ciimpl Debug for Nothing { 1365fad3a1d3Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1366fad3a1d3Sopenharmony_ci f.write_str("Nothing") 1367fad3a1d3Sopenharmony_ci } 1368fad3a1d3Sopenharmony_ci} 1369fad3a1d3Sopenharmony_ci 1370fad3a1d3Sopenharmony_ci#[cfg(feature = "extra-traits")] 1371fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 1372fad3a1d3Sopenharmony_ciimpl Eq for Nothing {} 1373fad3a1d3Sopenharmony_ci 1374fad3a1d3Sopenharmony_ci#[cfg(feature = "extra-traits")] 1375fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 1376fad3a1d3Sopenharmony_ciimpl PartialEq for Nothing { 1377fad3a1d3Sopenharmony_ci fn eq(&self, _other: &Self) -> bool { 1378fad3a1d3Sopenharmony_ci true 1379fad3a1d3Sopenharmony_ci } 1380fad3a1d3Sopenharmony_ci} 1381fad3a1d3Sopenharmony_ci 1382fad3a1d3Sopenharmony_ci#[cfg(feature = "extra-traits")] 1383fad3a1d3Sopenharmony_ci#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 1384fad3a1d3Sopenharmony_ciimpl Hash for Nothing { 1385fad3a1d3Sopenharmony_ci fn hash<H: Hasher>(&self, _state: &mut H) {} 1386fad3a1d3Sopenharmony_ci} 1387