1421 lines · 46.6 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT //! 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<T>`] 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<T>`]: 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<Field, Token![,]>,//! }//! #//! # enum ItemEnum {}//!//! impl Parse for Item {//!     fn parse(input: ParseStream) -> Result<Self> {//!         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<Self> {//!         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<Self> {//! #         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<String, Value>")?;//! #     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<PathSegment, Token![::]> = 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::<PathSegment, Token![::]>::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::<Expr, Token![,]>::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;use crate::punctuated::Punctuated;use crate::token::Token;use proc_macro2::{Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};#[cfg(feature = "printing")]use quote::ToTokens;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::panic::{RefUnwindSafe, UnwindSafe};use std::rc::Rc;use std::str::FromStr; pub use crate::error::{Error, Result};pub use crate::lookahead::{End, 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]: selfpub trait Parse: Sized {    fn parse(input: ParseStream) -> Result<Self>;} /// 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]: selfpub 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<T>`.////// ## 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-functionspub struct ParseBuffer<'a> {    scope: Span,    // Instead of Cell<Cursor<'a>> 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<Cursor<'a>> 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<Cursor<'static>>,    marker: PhantomData<Cursor<'a>>,    unexpected: Cell<Option<Rc<Cell<Unexpected>>>>,} impl<'a> Drop for ParseBuffer<'a> {    fn drop(&mut self) {        if let Some((unexpected_span, delimiter)) = 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, delimiter));            }        }    }} 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)    }} impl<'a> UnwindSafe for ParseBuffer<'a> {}impl<'a> RefUnwindSafe for ParseBuffer<'a> {} /// 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<proc_macro2::TokenStream> {/// #     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<fn(Cursor<'c>) -> 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<T: Display>(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<'c>, Cursor<'a>>(to) }} pub(crate) fn new_parse_buffer(    scope: Span,    cursor: Cursor,    unexpected: Rc<Cell<Unexpected>>,) -> ParseBuffer {    ParseBuffer {        scope,        // See comment on `cell` in the struct definition.        cell: Cell::new(unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) }),        marker: PhantomData,        unexpected: Cell::new(Some(unexpected)),    }} pub(crate) enum Unexpected {    None,    Some(Span, Delimiter),    Chain(Rc<Cell<Unexpected>>),} 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, delimiter) => Unexpected::Some(*span, *delimiter),            Unexpected::Chain(next) => Unexpected::Chain(next.clone()),        }    }} // We call this on Cell<Unexpected> and Cell<Option<T>> where temporarily// swapping in a None is cheap.fn cell_clone<T: Default + Clone>(cell: &Cell<T>) -> T {    let prev = cell.take();    let ret = prev.clone();    cell.set(prev);    ret} fn inner_unexpected(buffer: &ParseBuffer) -> (Rc<Cell<Unexpected>>, Option<(Span, Delimiter)>) {    let mut unexpected = get_unexpected(buffer);    loop {        match cell_clone(&unexpected) {            Unexpected::None => return (unexpected, None),            Unexpected::Some(span, delimiter) => return (unexpected, Some((span, delimiter))),            Unexpected::Chain(next) => unexpected = next,        }    }} pub(crate) fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Unexpected>> {    cell_clone(&buffer.unexpected).unwrap()} fn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option<(Span, Delimiter)> {    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(), cursor.scope_delimiter()))    }} impl<'a> ParseBuffer<'a> {    /// Parses a syntax tree node of type `T`, advancing the position of our    /// parse stream past it.    pub fn parse<T: Parse>(&self) -> Result<T> {        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<Attribute>,    ///     struct_token: Token![struct],    ///     name: Ident,    ///     semi_token: Token![;],    /// }    ///    /// impl Parse for UnitStruct {    ///     fn parse(input: ParseStream) -> Result<Self> {    ///         Ok(UnitStruct {    ///             attrs: input.call(Attribute::parse_outer)?,    ///             struct_token: input.parse()?,

Lines 1–500 of 1421.