//! Parsing interface for parsing a token stream into a syntax tree node. //! //! Parsing in Syn is built on parser functions that take in a [`ParseStream`] //! and produce a [`Result`] where `T` is some syntax tree node. Underlying //! these parser functions is a lower level mechanism built around the //! [`Cursor`] type. `Cursor` is a cheaply copyable cursor over a range of //! tokens in a token stream. //! //! [`Result`]: Result //! [`Cursor`]: crate::buffer::Cursor //! //! # Example //! //! Here is a snippet of parsing code to get a feel for the style of the //! library. We define data structures for a subset of Rust syntax including //! enums (not shown) and structs, then provide implementations of the [`Parse`] //! trait to parse these syntax tree data structures from a token stream. //! //! Once `Parse` impls have been defined, they can be called conveniently from a //! procedural macro through [`parse_macro_input!`] as shown at the bottom of //! the snippet. If the caller provides syntactically invalid input to the //! procedural macro, they will receive a helpful compiler error message //! pointing out the exact token that triggered the failure to parse. //! //! [`parse_macro_input!`]: crate::parse_macro_input! //! //! ``` //! # extern crate proc_macro; //! # //! use proc_macro::TokenStream; //! use syn::{braced, parse_macro_input, token, Field, Ident, Result, Token}; //! use syn::parse::{Parse, ParseStream}; //! use syn::punctuated::Punctuated; //! //! enum Item { //! Struct(ItemStruct), //! Enum(ItemEnum), //! } //! //! struct ItemStruct { //! struct_token: Token![struct], //! ident: Ident, //! brace_token: token::Brace, //! fields: Punctuated, //! } //! # //! # enum ItemEnum {} //! //! impl Parse for Item { //! fn parse(input: ParseStream) -> Result { //! let lookahead = input.lookahead1(); //! if lookahead.peek(Token![struct]) { //! input.parse().map(Item::Struct) //! } else if lookahead.peek(Token![enum]) { //! input.parse().map(Item::Enum) //! } else { //! Err(lookahead.error()) //! } //! } //! } //! //! impl Parse for ItemStruct { //! fn parse(input: ParseStream) -> Result { //! let content; //! Ok(ItemStruct { //! struct_token: input.parse()?, //! ident: input.parse()?, //! brace_token: braced!(content in input), //! fields: content.parse_terminated(Field::parse_named, Token![,])?, //! }) //! } //! } //! # //! # impl Parse for ItemEnum { //! # fn parse(input: ParseStream) -> Result { //! # unimplemented!() //! # } //! # } //! //! # const IGNORE: &str = stringify! { //! #[proc_macro] //! # }; //! pub fn my_macro(tokens: TokenStream) -> TokenStream { //! let input = parse_macro_input!(tokens as Item); //! //! /* ... */ //! # TokenStream::new() //! } //! ``` //! //! # The `syn::parse*` functions //! //! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve //! as an entry point for parsing syntax tree nodes that can be parsed in an //! obvious default way. These functions can return any syntax tree node that //! implements the [`Parse`] trait, which includes most types in Syn. //! //! [`syn::parse`]: crate::parse() //! [`syn::parse2`]: crate::parse2() //! [`syn::parse_str`]: crate::parse_str() //! //! ``` //! use syn::Type; //! //! # fn run_parser() -> syn::Result<()> { //! let t: Type = syn::parse_str("std::collections::HashMap")?; //! # Ok(()) //! # } //! # //! # run_parser().unwrap(); //! ``` //! //! The [`parse_quote!`] macro also uses this approach. //! //! [`parse_quote!`]: crate::parse_quote! //! //! # The `Parser` trait //! //! Some types can be parsed in several ways depending on context. For example //! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like //! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`] //! may or may not allow trailing punctuation, and parsing it the wrong way //! would either reject valid input or accept invalid input. //! //! [`Attribute`]: crate::Attribute //! [`Punctuated`]: crate::punctuated //! //! The `Parse` trait is not implemented in these cases because there is no good //! behavior to consider the default. //! //! ```compile_fail //! # extern crate proc_macro; //! # //! # use syn::punctuated::Punctuated; //! # use syn::{PathSegment, Result, Token}; //! # //! # fn f(tokens: proc_macro::TokenStream) -> Result<()> { //! # //! // Can't parse `Punctuated` without knowing whether trailing punctuation //! // should be allowed in this context. //! let path: Punctuated = syn::parse(tokens)?; //! # //! # Ok(()) //! # } //! ``` //! //! In these cases the types provide a choice of parser functions rather than a //! single `Parse` implementation, and those parser functions can be invoked //! through the [`Parser`] trait. //! //! //! ``` //! # extern crate proc_macro; //! # //! use proc_macro::TokenStream; //! use syn::parse::Parser; //! use syn::punctuated::Punctuated; //! use syn::{Attribute, Expr, PathSegment, Result, Token}; //! //! fn call_some_parser_methods(input: TokenStream) -> Result<()> { //! // Parse a nonempty sequence of path segments separated by `::` punctuation //! // with no trailing punctuation. //! let tokens = input.clone(); //! let parser = Punctuated::::parse_separated_nonempty; //! let _path = parser.parse(tokens)?; //! //! // Parse a possibly empty sequence of expressions terminated by commas with //! // an optional trailing punctuation. //! let tokens = input.clone(); //! let parser = Punctuated::::parse_terminated; //! let _args = parser.parse(tokens)?; //! //! // Parse zero or more outer attributes but not inner attributes. //! let tokens = input.clone(); //! let parser = Attribute::parse_outer; //! let _attrs = parser.parse(tokens)?; //! //! Ok(()) //! } //! ``` #[path = "discouraged.rs"] pub mod discouraged; use crate::buffer::{Cursor, TokenBuffer}; use crate::error; use crate::lookahead; #[cfg(feature = "proc-macro")] use crate::proc_macro; use crate::punctuated::Punctuated; use crate::token::Token; use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree}; use std::cell::Cell; use std::fmt::{self, Debug, Display}; #[cfg(feature = "extra-traits")] use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::ops::Deref; use std::rc::Rc; use std::str::FromStr; pub use crate::error::{Error, Result}; pub use crate::lookahead::{Lookahead1, Peek}; /// Parsing interface implemented by all types that can be parsed in a default /// way from a token stream. /// /// Refer to the [module documentation] for details about implementing and using /// the `Parse` trait. /// /// [module documentation]: self pub trait Parse: Sized { fn parse(input: ParseStream) -> Result; } /// Input to a Syn parser function. /// /// See the methods of this type under the documentation of [`ParseBuffer`]. For /// an overview of parsing in Syn, refer to the [module documentation]. /// /// [module documentation]: self pub type ParseStream<'a> = &'a ParseBuffer<'a>; /// Cursor position within a buffered token stream. /// /// This type is more commonly used through the type alias [`ParseStream`] which /// is an alias for `&ParseBuffer`. /// /// `ParseStream` is the input type for all parser functions in Syn. They have /// the signature `fn(ParseStream) -> Result`. /// /// ## Calling a parser function /// /// There is no public way to construct a `ParseBuffer`. Instead, if you are /// looking to invoke a parser function that requires `ParseStream` as input, /// you will need to go through one of the public parsing entry points. /// /// - The [`parse_macro_input!`] macro if parsing input of a procedural macro; /// - One of [the `syn::parse*` functions][syn-parse]; or /// - A method of the [`Parser`] trait. /// /// [`parse_macro_input!`]: crate::parse_macro_input! /// [syn-parse]: self#the-synparse-functions pub struct ParseBuffer<'a> { scope: Span, // Instead of Cell> so that ParseBuffer<'a> is covariant in 'a. // The rest of the code in this module needs to be careful that only a // cursor derived from this `cell` is ever assigned to this `cell`. // // Cell> cannot be covariant in 'a because then we could take a // ParseBuffer<'a>, upcast to ParseBuffer<'short> for some lifetime shorter // than 'a, and then assign a Cursor<'short> into the Cell. // // By extension, it would not be safe to expose an API that accepts a // Cursor<'a> and trusts that it lives as long as the cursor currently in // the cell. cell: Cell>, marker: PhantomData>, unexpected: Cell>>>, } impl<'a> Drop for ParseBuffer<'a> { fn drop(&mut self) { if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(self.cursor()) { let (inner, old_span) = inner_unexpected(self); if old_span.is_none() { inner.set(Unexpected::Some(unexpected_span)); } } } } impl<'a> Display for ParseBuffer<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.cursor().token_stream(), f) } } impl<'a> Debug for ParseBuffer<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.cursor().token_stream(), f) } } /// Cursor state associated with speculative parsing. /// /// This type is the input of the closure provided to [`ParseStream::step`]. /// /// [`ParseStream::step`]: ParseBuffer::step /// /// # Example /// /// ``` /// use proc_macro2::TokenTree; /// use syn::Result; /// use syn::parse::ParseStream; /// /// // This function advances the stream past the next occurrence of `@`. If /// // no `@` is present in the stream, the stream position is unchanged and /// // an error is returned. /// fn skip_past_next_at(input: ParseStream) -> Result<()> { /// input.step(|cursor| { /// let mut rest = *cursor; /// while let Some((tt, next)) = rest.token_tree() { /// match &tt { /// TokenTree::Punct(punct) if punct.as_char() == '@' => { /// return Ok(((), next)); /// } /// _ => rest = next, /// } /// } /// Err(cursor.error("no `@` was found after this point")) /// }) /// } /// # /// # fn remainder_after_skipping_past_next_at( /// # input: ParseStream, /// # ) -> Result { /// # skip_past_next_at(input)?; /// # input.parse() /// # } /// # /// # use syn::parse::Parser; /// # let remainder = remainder_after_skipping_past_next_at /// # .parse_str("a @ b c") /// # .unwrap(); /// # assert_eq!(remainder.to_string(), "b c"); /// ``` pub struct StepCursor<'c, 'a> { scope: Span, // This field is covariant in 'c. cursor: Cursor<'c>, // This field is contravariant in 'c. Together these make StepCursor // invariant in 'c. Also covariant in 'a. The user cannot cast 'c to a // different lifetime but can upcast into a StepCursor with a shorter // lifetime 'a. // // As long as we only ever construct a StepCursor for which 'c outlives 'a, // this means if ever a StepCursor<'c, 'a> exists we are guaranteed that 'c // outlives 'a. marker: PhantomData) -> Cursor<'a>>, } impl<'c, 'a> Deref for StepCursor<'c, 'a> { type Target = Cursor<'c>; fn deref(&self) -> &Self::Target { &self.cursor } } impl<'c, 'a> Copy for StepCursor<'c, 'a> {} impl<'c, 'a> Clone for StepCursor<'c, 'a> { fn clone(&self) -> Self { *self } } impl<'c, 'a> StepCursor<'c, 'a> { /// Triggers an error at the current position of the parse stream. /// /// The `ParseStream::step` invocation will return this same error without /// advancing the stream state. pub fn error(self, message: T) -> Error { error::new_at(self.scope, self.cursor, message) } } pub(crate) fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> { // Refer to the comments within the StepCursor definition. We use the // fact that a StepCursor<'c, 'a> exists as proof that 'c outlives 'a. // Cursor is covariant in its lifetime parameter so we can cast a // Cursor<'c> to one with the shorter lifetime Cursor<'a>. let _ = proof; unsafe { mem::transmute::, Cursor<'a>>(to) } } pub(crate) fn new_parse_buffer( scope: Span, cursor: Cursor, unexpected: Rc>, ) -> ParseBuffer { ParseBuffer { scope, // See comment on `cell` in the struct definition. cell: Cell::new(unsafe { mem::transmute::>(cursor) }), marker: PhantomData, unexpected: Cell::new(Some(unexpected)), } } pub(crate) enum Unexpected { None, Some(Span), Chain(Rc>), } impl Default for Unexpected { fn default() -> Self { Unexpected::None } } impl Clone for Unexpected { fn clone(&self) -> Self { match self { Unexpected::None => Unexpected::None, Unexpected::Some(span) => Unexpected::Some(*span), Unexpected::Chain(next) => Unexpected::Chain(next.clone()), } } } // We call this on Cell and Cell> where temporarily // swapping in a None is cheap. fn cell_clone(cell: &Cell) -> T { let prev = cell.take(); let ret = prev.clone(); cell.set(prev); ret } fn inner_unexpected(buffer: &ParseBuffer) -> (Rc>, Option) { let mut unexpected = get_unexpected(buffer); loop { match cell_clone(&unexpected) { Unexpected::None => return (unexpected, None), Unexpected::Some(span) => return (unexpected, Some(span)), Unexpected::Chain(next) => unexpected = next, } } } pub(crate) fn get_unexpected(buffer: &ParseBuffer) -> Rc> { cell_clone(&buffer.unexpected).unwrap() } fn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option { if cursor.eof() { return None; } while let Some((inner, _span, rest)) = cursor.group(Delimiter::None) { if let Some(unexpected) = span_of_unexpected_ignoring_nones(inner) { return Some(unexpected); } cursor = rest; } if cursor.eof() { None } else { Some(cursor.span()) } } impl<'a> ParseBuffer<'a> { /// Parses a syntax tree node of type `T`, advancing the position of our /// parse stream past it. pub fn parse(&self) -> Result { T::parse(self) } /// Calls the given parser function to parse a syntax tree node of type `T` /// from this stream. /// /// # Example /// /// The parser below invokes [`Attribute::parse_outer`] to parse a vector of /// zero or more outer attributes. /// /// [`Attribute::parse_outer`]: crate::Attribute::parse_outer /// /// ``` /// use syn::{Attribute, Ident, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses a unit struct with attributes. /// // /// // #[path = "s.tmpl"] /// // struct S; /// struct UnitStruct { /// attrs: Vec, /// struct_token: Token![struct], /// name: Ident, /// semi_token: Token![;], /// } /// /// impl Parse for UnitStruct { /// fn parse(input: ParseStream) -> Result { /// Ok(UnitStruct { /// attrs: input.call(Attribute::parse_outer)?, /// struct_token: input.parse()?, /// name: input.parse()?, /// semi_token: input.parse()?, /// }) /// } /// } /// ``` pub fn call(&self, function: fn(ParseStream) -> Result) -> Result { function(self) } /// Looks at the next token in the parse stream to determine whether it /// matches the requested type of token. /// /// Does not advance the position of the parse stream. /// /// # Syntax /// /// Note that this method does not use turbofish syntax. Pass the peek type /// inside of parentheses. /// /// - `input.peek(Token![struct])` /// - `input.peek(Token![==])` /// - `input.peek(syn::Ident)` *(does not accept keywords)* /// - `input.peek(syn::Ident::peek_any)` /// - `input.peek(Lifetime)` /// - `input.peek(token::Brace)` /// /// # Example /// /// In this example we finish parsing the list of supertraits when the next /// token in the input is either `where` or an opening curly brace. /// /// ``` /// use syn::{braced, token, Generics, Ident, Result, Token, TypeParamBound}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// // Parses a trait definition containing no associated items. /// // /// // trait Marker<'de, T>: A + B<'de> where Box: Clone {} /// struct MarkerTrait { /// trait_token: Token![trait], /// ident: Ident, /// generics: Generics, /// colon_token: Option, /// supertraits: Punctuated, /// brace_token: token::Brace, /// } /// /// impl Parse for MarkerTrait { /// fn parse(input: ParseStream) -> Result { /// let trait_token: Token![trait] = input.parse()?; /// let ident: Ident = input.parse()?; /// let mut generics: Generics = input.parse()?; /// let colon_token: Option = input.parse()?; /// /// let mut supertraits = Punctuated::new(); /// if colon_token.is_some() { /// loop { /// supertraits.push_value(input.parse()?); /// if input.peek(Token![where]) || input.peek(token::Brace) { /// break; /// } /// supertraits.push_punct(input.parse()?); /// } /// } /// /// generics.where_clause = input.parse()?; /// let content; /// let empty_brace_token = braced!(content in input); /// /// Ok(MarkerTrait { /// trait_token, /// ident, /// generics, /// colon_token, /// supertraits, /// brace_token: empty_brace_token, /// }) /// } /// } /// ``` pub fn peek(&self, token: T) -> bool { let _ = token; T::Token::peek(self.cursor()) } /// Looks at the second-next token in the parse stream. /// /// This is commonly useful as a way to implement contextual keywords. /// /// # Example /// /// This example needs to use `peek2` because the symbol `union` is not a /// keyword in Rust. We can't use just `peek` and decide to parse a union if /// the very next token is `union`, because someone is free to write a `mod /// union` and a macro invocation that looks like `union::some_macro! { ... /// }`. In other words `union` is a contextual keyword. /// /// ``` /// use syn::{Ident, ItemUnion, Macro, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses either a union or a macro invocation. /// enum UnionOrMacro { /// // union MaybeUninit { uninit: (), value: T } /// Union(ItemUnion), /// // lazy_static! { ... } /// Macro(Macro), /// } /// /// impl Parse for UnionOrMacro { /// fn parse(input: ParseStream) -> Result { /// if input.peek(Token![union]) && input.peek2(Ident) { /// input.parse().map(UnionOrMacro::Union) /// } else { /// input.parse().map(UnionOrMacro::Macro) /// } /// } /// } /// ``` pub fn peek2(&self, token: T) -> bool { fn peek2(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool { if let Some(group) = buffer.cursor().group(Delimiter::None) { if group.0.skip().map_or(false, peek) { return true; } } buffer.cursor().skip().map_or(false, peek) } let _ = token; peek2(self, T::Token::peek) } /// Looks at the third-next token in the parse stream. pub fn peek3(&self, token: T) -> bool { fn peek3(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool { if let Some(group) = buffer.cursor().group(Delimiter::None) { if group.0.skip().and_then(Cursor::skip).map_or(false, peek) { return true; } } buffer .cursor() .skip() .and_then(Cursor::skip) .map_or(false, peek) } let _ = token; peek3(self, T::Token::peek) } /// Parses zero or more occurrences of `T` separated by punctuation of type /// `P`, with optional trailing punctuation. /// /// Parsing continues until the end of this parse stream. The entire content /// of this parse stream must consist of `T` and `P`. /// /// # Example /// /// ``` /// # use quote::quote; /// # /// use syn::{parenthesized, token, Ident, Result, Token, Type}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// // Parse a simplified tuple struct syntax like: /// // /// // struct S(A, B); /// struct TupleStruct { /// struct_token: Token![struct], /// ident: Ident, /// paren_token: token::Paren, /// fields: Punctuated, /// semi_token: Token![;], /// } /// /// impl Parse for TupleStruct { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(TupleStruct { /// struct_token: input.parse()?, /// ident: input.parse()?, /// paren_token: parenthesized!(content in input), /// fields: content.parse_terminated(Type::parse, Token![,])?, /// semi_token: input.parse()?, /// }) /// } /// } /// # /// # let input = quote! { /// # struct S(A, B); /// # }; /// # syn::parse2::(input).unwrap(); /// ``` /// /// # See also /// /// If your separator is anything more complicated than an invocation of the /// `Token!` macro, this method won't be applicable and you can instead /// directly use `Punctuated`'s parser functions: [`parse_terminated`], /// [`parse_separated_nonempty`] etc. /// /// [`parse_terminated`]: Punctuated::parse_terminated /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty /// /// ``` /// use syn::{custom_keyword, Expr, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// mod kw { /// syn::custom_keyword!(fin); /// } /// /// struct Fin(kw::fin, Token![;]); /// /// impl Parse for Fin { /// fn parse(input: ParseStream) -> Result { /// Ok(Self(input.parse()?, input.parse()?)) /// } /// } /// /// struct Thing { /// steps: Punctuated, /// } /// /// impl Parse for Thing { /// fn parse(input: ParseStream) -> Result { /// # if true { /// Ok(Thing { /// steps: Punctuated::parse_terminated(input)?, /// }) /// # } else { /// // or equivalently, this means the same thing: /// # Ok(Thing { /// steps: input.call(Punctuated::parse_terminated)?, /// # }) /// # } /// } /// } /// ``` pub fn parse_terminated( &self, parser: fn(ParseStream) -> Result, separator: P, ) -> Result> where P: Peek, P::Token: Parse, { let _ = separator; Punctuated::parse_terminated_with(self, parser) } /// Returns whether there are tokens remaining in this stream. /// /// This method returns true at the end of the content of a set of /// delimiters, as well as at the very end of the complete macro input. /// /// # Example /// /// ``` /// use syn::{braced, token, Ident, Item, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses a Rust `mod m { ... }` containing zero or more items. /// struct Mod { /// mod_token: Token![mod], /// name: Ident, /// brace_token: token::Brace, /// items: Vec, /// } /// /// impl Parse for Mod { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(Mod { /// mod_token: input.parse()?, /// name: input.parse()?, /// brace_token: braced!(content in input), /// items: { /// let mut items = Vec::new(); /// while !content.is_empty() { /// items.push(content.parse()?); /// } /// items /// }, /// }) /// } /// } /// ``` pub fn is_empty(&self) -> bool { self.cursor().eof() } /// Constructs a helper for peeking at the next token in this stream and /// building an error message if it is not one of a set of expected tokens. /// /// # Example /// /// ``` /// use syn::{ConstParam, Ident, Lifetime, LifetimeParam, Result, Token, TypeParam}; /// use syn::parse::{Parse, ParseStream}; /// /// // A generic parameter, a single one of the comma-separated elements inside /// // angle brackets in: /// // /// // fn f() { ... } /// // /// // On invalid input, lookahead gives us a reasonable error message. /// // /// // error: expected one of: identifier, lifetime, `const` /// // | /// // 5 | fn f() {} /// // | ^ /// enum GenericParam { /// Type(TypeParam), /// Lifetime(LifetimeParam), /// Const(ConstParam), /// } /// /// impl Parse for GenericParam { /// fn parse(input: ParseStream) -> Result { /// let lookahead = input.lookahead1(); /// if lookahead.peek(Ident) { /// input.parse().map(GenericParam::Type) /// } else if lookahead.peek(Lifetime) { /// input.parse().map(GenericParam::Lifetime) /// } else if lookahead.peek(Token![const]) { /// input.parse().map(GenericParam::Const) /// } else { /// Err(lookahead.error()) /// } /// } /// } /// ``` pub fn lookahead1(&self) -> Lookahead1<'a> { lookahead::new(self.scope, self.cursor()) } /// Forks a parse stream so that parsing tokens out of either the original /// or the fork does not advance the position of the other. /// /// # Performance /// /// Forking a parse stream is a cheap fixed amount of work and does not /// involve copying token buffers. Where you might hit performance problems /// is if your macro ends up parsing a large amount of content more than /// once. /// /// ``` /// # use syn::{Expr, Result}; /// # use syn::parse::ParseStream; /// # /// # fn bad(input: ParseStream) -> Result { /// // Do not do this. /// if input.fork().parse::().is_ok() { /// return input.parse::(); /// } /// # unimplemented!() /// # } /// ``` /// /// As a rule, avoid parsing an unbounded amount of tokens out of a forked /// parse stream. Only use a fork when the amount of work performed against /// the fork is small and bounded. /// /// When complex speculative parsing against the forked stream is /// unavoidable, use [`parse::discouraged::Speculative`] to advance the /// original stream once the fork's parse is determined to have been /// successful. /// /// For a lower level way to perform speculative parsing at the token level, /// consider using [`ParseStream::step`] instead. /// /// [`parse::discouraged::Speculative`]: discouraged::Speculative /// [`ParseStream::step`]: ParseBuffer::step /// /// # Example /// /// The parse implementation shown here parses possibly restricted `pub` /// visibilities. /// /// - `pub` /// - `pub(crate)` /// - `pub(self)` /// - `pub(super)` /// - `pub(in some::path)` /// /// To handle the case of visibilities inside of tuple structs, the parser /// needs to distinguish parentheses that specify visibility restrictions /// from parentheses that form part of a tuple type. /// /// ``` /// # struct A; /// # struct B; /// # struct C; /// # /// struct S(pub(crate) A, pub (B, C)); /// ``` /// /// In this example input the first tuple struct element of `S` has /// `pub(crate)` visibility while the second tuple struct element has `pub` /// visibility; the parentheses around `(B, C)` are part of the type rather /// than part of a visibility restriction. /// /// The parser uses a forked parse stream to check the first token inside of /// parentheses after the `pub` keyword. This is a small bounded amount of /// work performed against the forked parse stream. /// /// ``` /// use syn::{parenthesized, token, Ident, Path, Result, Token}; /// use syn::ext::IdentExt; /// use syn::parse::{Parse, ParseStream}; /// /// struct PubVisibility { /// pub_token: Token![pub], /// restricted: Option, /// } /// /// struct Restricted { /// paren_token: token::Paren, /// in_token: Option, /// path: Path, /// } /// /// impl Parse for PubVisibility { /// fn parse(input: ParseStream) -> Result { /// let pub_token: Token![pub] = input.parse()?; /// /// if input.peek(token::Paren) { /// let ahead = input.fork(); /// let mut content; /// parenthesized!(content in ahead); /// /// if content.peek(Token![crate]) /// || content.peek(Token![self]) /// || content.peek(Token![super]) /// { /// return Ok(PubVisibility { /// pub_token, /// restricted: Some(Restricted { /// paren_token: parenthesized!(content in input), /// in_token: None, /// path: Path::from(content.call(Ident::parse_any)?), /// }), /// }); /// } else if content.peek(Token![in]) { /// return Ok(PubVisibility { /// pub_token, /// restricted: Some(Restricted { /// paren_token: parenthesized!(content in input), /// in_token: Some(content.parse()?), /// path: content.call(Path::parse_mod_style)?, /// }), /// }); /// } /// } /// /// Ok(PubVisibility { /// pub_token, /// restricted: None, /// }) /// } /// } /// ``` pub fn fork(&self) -> Self { ParseBuffer { scope: self.scope, cell: self.cell.clone(), marker: PhantomData, // Not the parent's unexpected. Nothing cares whether the clone // parses all the way unless we `advance_to`. unexpected: Cell::new(Some(Rc::new(Cell::new(Unexpected::None)))), } } /// Triggers an error at the current position of the parse stream. /// /// # Example /// /// ``` /// use syn::{Expr, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Some kind of loop: `while` or `for` or `loop`. /// struct Loop { /// expr: Expr, /// } /// /// impl Parse for Loop { /// fn parse(input: ParseStream) -> Result { /// if input.peek(Token![while]) /// || input.peek(Token![for]) /// || input.peek(Token![loop]) /// { /// Ok(Loop { /// expr: input.parse()?, /// }) /// } else { /// Err(input.error("expected some kind of loop")) /// } /// } /// } /// ``` pub fn error(&self, message: T) -> Error { error::new_at(self.scope, self.cursor(), message) } /// Speculatively parses tokens from this parse stream, advancing the /// position of this stream only if parsing succeeds. /// /// This is a powerful low-level API used for defining the `Parse` impls of /// the basic built-in token types. It is not something that will be used /// widely outside of the Syn codebase. /// /// # Example /// /// ``` /// use proc_macro2::TokenTree; /// use syn::Result; /// use syn::parse::ParseStream; /// /// // This function advances the stream past the next occurrence of `@`. If /// // no `@` is present in the stream, the stream position is unchanged and /// // an error is returned. /// fn skip_past_next_at(input: ParseStream) -> Result<()> { /// input.step(|cursor| { /// let mut rest = *cursor; /// while let Some((tt, next)) = rest.token_tree() { /// match &tt { /// TokenTree::Punct(punct) if punct.as_char() == '@' => { /// return Ok(((), next)); /// } /// _ => rest = next, /// } /// } /// Err(cursor.error("no `@` was found after this point")) /// }) /// } /// # /// # fn remainder_after_skipping_past_next_at( /// # input: ParseStream, /// # ) -> Result { /// # skip_past_next_at(input)?; /// # input.parse() /// # } /// # /// # use syn::parse::Parser; /// # let remainder = remainder_after_skipping_past_next_at /// # .parse_str("a @ b c") /// # .unwrap(); /// # assert_eq!(remainder.to_string(), "b c"); /// ``` pub fn step(&self, function: F) -> Result where F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>, { // Since the user's function is required to work for any 'c, we know // that the Cursor<'c> they return is either derived from the input // StepCursor<'c, 'a> or from a Cursor<'static>. // // It would not be legal to write this function without the invariant // lifetime 'c in StepCursor<'c, 'a>. If this function were written only // in terms of 'a, the user could take our ParseBuffer<'a>, upcast it to // a ParseBuffer<'short> which some shorter lifetime than 'a, invoke // `step` on their ParseBuffer<'short> with a closure that returns // Cursor<'short>, and we would wrongly write that Cursor<'short> into // the Cell intended to hold Cursor<'a>. // // In some cases it may be necessary for R to contain a Cursor<'a>. // Within Syn we solve this using `advance_step_cursor` which uses the // existence of a StepCursor<'c, 'a> as proof that it is safe to cast // from Cursor<'c> to Cursor<'a>. If needed outside of Syn, it would be // safe to expose that API as a method on StepCursor. let (node, rest) = function(StepCursor { scope: self.scope, cursor: self.cell.get(), marker: PhantomData, })?; self.cell.set(rest); Ok(node) } /// Returns the `Span` of the next token in the parse stream, or /// `Span::call_site()` if this parse stream has completely exhausted its /// input `TokenStream`. pub fn span(&self) -> Span { let cursor = self.cursor(); if cursor.eof() { self.scope } else { crate::buffer::open_span_of_group(cursor) } } /// Provides low-level access to the token representation underlying this /// parse stream. /// /// Cursors are immutable so no operations you perform against the cursor /// will affect the state of this parse stream. /// /// # Example /// /// ``` /// use proc_macro2::TokenStream; /// use syn::buffer::Cursor; /// use syn::parse::{ParseStream, Result}; /// /// // Run a parser that returns T, but get its output as TokenStream instead of T. /// // This works without T needing to implement ToTokens. /// fn recognize_token_stream( /// recognizer: fn(ParseStream) -> Result, /// ) -> impl Fn(ParseStream) -> Result { /// move |input| { /// let begin = input.cursor(); /// recognizer(input)?; /// let end = input.cursor(); /// Ok(tokens_between(begin, end)) /// } /// } /// /// // Collect tokens between two cursors as a TokenStream. /// fn tokens_between(begin: Cursor, end: Cursor) -> TokenStream { /// assert!(begin <= end); /// /// let mut cursor = begin; /// let mut tokens = TokenStream::new(); /// while cursor < end { /// let (token, next) = cursor.token_tree().unwrap(); /// tokens.extend(std::iter::once(token)); /// cursor = next; /// } /// tokens /// } /// /// fn main() { /// use quote::quote; /// use syn::parse::{Parse, Parser}; /// use syn::Token; /// /// // Parse syn::Type as a TokenStream, surrounded by angle brackets. /// fn example(input: ParseStream) -> Result { /// let _langle: Token![<] = input.parse()?; /// let ty = recognize_token_stream(syn::Type::parse)(input)?; /// let _rangle: Token![>] = input.parse()?; /// Ok(ty) /// } /// /// let tokens = quote! { u8> }; /// println!("{}", example.parse2(tokens).unwrap()); /// } /// ``` pub fn cursor(&self) -> Cursor<'a> { self.cell.get() } fn check_unexpected(&self) -> Result<()> { match inner_unexpected(self).1 { Some(span) => Err(Error::new(span, "unexpected token")), None => Ok(()), } } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for Box { fn parse(input: ParseStream) -> Result { input.parse().map(Box::new) } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if T::peek(input.cursor()) { Ok(Some(input.parse()?)) } else { Ok(None) } } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for TokenStream { fn parse(input: ParseStream) -> Result { input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty()))) } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for TokenTree { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.token_tree() { Some((tt, rest)) => Ok((tt, rest)), None => Err(cursor.error("expected token tree")), }) } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for Group { fn parse(input: ParseStream) -> Result { input.step(|cursor| { if let Some((group, rest)) = cursor.any_group_token() { if group.delimiter() != Delimiter::None { return Ok((group, rest)); } } Err(cursor.error("expected group token")) }) } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for Punct { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.punct() { Some((punct, rest)) => Ok((punct, rest)), None => Err(cursor.error("expected punctuation token")), }) } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for Literal { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.literal() { Some((literal, rest)) => Ok((literal, rest)), None => Err(cursor.error("expected literal token")), }) } } /// Parser that can parse Rust tokens into a particular syntax tree node. /// /// Refer to the [module documentation] for details about parsing in Syn. /// /// [module documentation]: self pub trait Parser: Sized { type Output; /// Parse a proc-macro2 token stream into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the stream, an error is returned. fn parse2(self, tokens: TokenStream) -> Result; /// Parse tokens of source code into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the stream, an error is returned. #[cfg(feature = "proc-macro")] #[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))] fn parse(self, tokens: proc_macro::TokenStream) -> Result { self.parse2(proc_macro2::TokenStream::from(tokens)) } /// Parse a string of Rust code into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the string, an error is returned. /// /// # Hygiene /// /// Every span in the resulting syntax tree will be set to resolve at the /// macro call site. fn parse_str(self, s: &str) -> Result { self.parse2(proc_macro2::TokenStream::from_str(s)?) } // Not public API. #[doc(hidden)] #[cfg(any(feature = "full", feature = "derive"))] fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result { let _ = scope; self.parse2(tokens) } } fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer { let scope = Span::call_site(); let cursor = tokens.begin(); let unexpected = Rc::new(Cell::new(Unexpected::None)); new_parse_buffer(scope, cursor, unexpected) } impl Parser for F where F: FnOnce(ParseStream) -> Result, { type Output = T; fn parse2(self, tokens: TokenStream) -> Result { let buf = TokenBuffer::new2(tokens); let state = tokens_to_parse_buffer(&buf); let node = self(&state)?; state.check_unexpected()?; if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { Err(Error::new(unexpected_span, "unexpected token")) } else { Ok(node) } } #[cfg(any(feature = "full", feature = "derive"))] fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result { let buf = TokenBuffer::new2(tokens); let cursor = buf.begin(); let unexpected = Rc::new(Cell::new(Unexpected::None)); let state = new_parse_buffer(scope, cursor, unexpected); let node = self(&state)?; state.check_unexpected()?; if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { Err(Error::new(unexpected_span, "unexpected token")) } else { Ok(node) } } } #[cfg(any(feature = "full", feature = "derive"))] pub(crate) fn parse_scoped(f: F, scope: Span, tokens: TokenStream) -> Result { f.__parse_scoped(scope, tokens) } /// An empty syntax tree node that consumes no tokens when parsed. /// /// This is useful for attribute macros that want to ensure they are not /// provided any attribute args. /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::parse_macro_input; /// use syn::parse::Nothing; /// /// # const IGNORE: &str = stringify! { /// #[proc_macro_attribute] /// # }; /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { /// parse_macro_input!(args as Nothing); /// /// /* ... */ /// # TokenStream::new() /// } /// ``` /// /// ```text /// error: unexpected token /// --> src/main.rs:3:19 /// | /// 3 | #[my_attr(asdf)] /// | ^^^^ /// ``` pub struct Nothing; impl Parse for Nothing { fn parse(_input: ParseStream) -> Result { Ok(Nothing) } } #[cfg(feature = "extra-traits")] #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] impl Debug for Nothing { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Nothing") } } #[cfg(feature = "extra-traits")] #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] impl Eq for Nothing {} #[cfg(feature = "extra-traits")] #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] impl PartialEq for Nothing { fn eq(&self, _other: &Self) -> bool { true } } #[cfg(feature = "extra-traits")] #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] impl Hash for Nothing { fn hash(&self, _state: &mut H) {} }