// SPDX-License-Identifier: Apache-2.0 OR MIT12use crate::error::Result;3use crate::parse::ParseBuffer;4use crate::token;5use proc_macro2::extra::DelimSpan;6use proc_macro2::Delimiter;78// Not public API.9#[doc(hidden)]10pub struct Parens<'a> {11#[doc(hidden)]12pub token: token::Paren,13#[doc(hidden)]14pub content: ParseBuffer<'a>,15}1617// Not public API.18#[doc(hidden)]19pub struct Braces<'a> {20#[doc(hidden)]21pub token: token::Brace,22#[doc(hidden)]23pub content: ParseBuffer<'a>,24}2526// Not public API.27#[doc(hidden)]28pub struct Brackets<'a> {29#[doc(hidden)]30pub token: token::Bracket,31#[doc(hidden)]32pub content: ParseBuffer<'a>,33}3435// Not public API.36#[cfg(any(feature = "full", feature = "derive"))]37#[doc(hidden)]38pub struct Group<'a> {39#[doc(hidden)]40pub token: token::Group,41#[doc(hidden)]42pub content: ParseBuffer<'a>,43}4445// Not public API.46#[doc(hidden)]47pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {48parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {49token: token::Paren(span),50content,51})52}5354// Not public API.55#[doc(hidden)]56pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {57parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {58token: token::Brace(span),59content,60})61}6263// Not public API.64#[doc(hidden)]65pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {66parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {67token: token::Bracket(span),68content,69})70}7172#[cfg(any(feature = "full", feature = "derive"))]73pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {74parse_delimited(input, Delimiter::None).map(|(span, content)| Group {75token: token::Group(span.join()),76content,77})78}7980fn parse_delimited<'a>(81input: &ParseBuffer<'a>,82delimiter: Delimiter,83) -> Result<(DelimSpan, ParseBuffer<'a>)> {84input.step(|cursor| {85if let Some((content, span, rest)) = cursor.group(delimiter) {86let scope = span.close();87let nested = crate::parse::advance_step_cursor(cursor, content);88let unexpected = crate::parse::get_unexpected(input);89let content = crate::parse::new_parse_buffer(scope, nested, unexpected);90Ok(((span, content), rest))91} else {92let message = match delimiter {93Delimiter::Parenthesis => "expected parentheses",94Delimiter::Brace => "expected curly braces",95Delimiter::Bracket => "expected square brackets",96Delimiter::None => "expected invisible group",97};98Err(cursor.error(message))99}100})101}102103/// Parse a set of parentheses and expose their content to subsequent parsers.104///105/// # Example106///107/// ```108/// # use quote::quote;109/// #110/// use syn::{parenthesized, token, Ident, Result, Token, Type};111/// use syn::parse::{Parse, ParseStream};112/// use syn::punctuated::Punctuated;113///114/// // Parse a simplified tuple struct syntax like:115/// //116/// // struct S(A, B);117/// struct TupleStruct {118/// struct_token: Token![struct],119/// ident: Ident,120/// paren_token: token::Paren,121/// fields: Punctuated<Type, Token![,]>,122/// semi_token: Token![;],123/// }124///125/// impl Parse for TupleStruct {126/// fn parse(input: ParseStream) -> Result<Self> {127/// let content;128/// Ok(TupleStruct {129/// struct_token: input.parse()?,130/// ident: input.parse()?,131/// paren_token: parenthesized!(content in input),132/// fields: content.parse_terminated(Type::parse, Token![,])?,133/// semi_token: input.parse()?,134/// })135/// }136/// }137/// #138/// # fn main() {139/// # let input = quote! {140/// # struct S(A, B);141/// # };142/// # syn::parse2::<TupleStruct>(input).unwrap();143/// # }144/// ```145#[macro_export]146#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]147macro_rules! parenthesized {148($content:ident in $cursor:expr) => {149match $crate::__private::parse_parens(&$cursor) {150$crate::__private::Ok(parens) => {151$content = parens.content;152parens.token153}154$crate::__private::Err(error) => {155return $crate::__private::Err(error);156}157}158};159}160161/// Parse a set of curly braces and expose their content to subsequent parsers.162///163/// # Example164///165/// ```166/// # use quote::quote;167/// #168/// use syn::{braced, token, Ident, Result, Token, Type};169/// use syn::parse::{Parse, ParseStream};170/// use syn::punctuated::Punctuated;171///172/// // Parse a simplified struct syntax like:173/// //174/// // struct S {175/// // a: A,176/// // b: B,177/// // }178/// struct Struct {179/// struct_token: Token![struct],180/// ident: Ident,181/// brace_token: token::Brace,182/// fields: Punctuated<Field, Token![,]>,183/// }184///185/// struct Field {186/// name: Ident,187/// colon_token: Token![:],188/// ty: Type,189/// }190///191/// impl Parse for Struct {192/// fn parse(input: ParseStream) -> Result<Self> {193/// let content;194/// Ok(Struct {195/// struct_token: input.parse()?,196/// ident: input.parse()?,197/// brace_token: braced!(content in input),198/// fields: content.parse_terminated(Field::parse, Token![,])?,199/// })200/// }201/// }202///203/// impl Parse for Field {204/// fn parse(input: ParseStream) -> Result<Self> {205/// Ok(Field {206/// name: input.parse()?,207/// colon_token: input.parse()?,208/// ty: input.parse()?,209/// })210/// }211/// }212/// #213/// # fn main() {214/// # let input = quote! {215/// # struct S {216/// # a: A,217/// # b: B,218/// # }219/// # };220/// # syn::parse2::<Struct>(input).unwrap();221/// # }222/// ```223#[macro_export]224#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]225macro_rules! braced {226($content:ident in $cursor:expr) => {227match $crate::__private::parse_braces(&$cursor) {228$crate::__private::Ok(braces) => {229$content = braces.content;230braces.token231}232$crate::__private::Err(error) => {233return $crate::__private::Err(error);234}235}236};237}238239/// Parse a set of square brackets and expose their content to subsequent240/// parsers.241///242/// # Example243///244/// ```245/// # use quote::quote;246/// #247/// use proc_macro2::TokenStream;248/// use syn::{bracketed, token, Result, Token};249/// use syn::parse::{Parse, ParseStream};250///251/// // Parse an outer attribute like:252/// //253/// // #[repr(C, packed)]254/// struct OuterAttribute {255/// pound_token: Token![#],256/// bracket_token: token::Bracket,257/// content: TokenStream,258/// }259///260/// impl Parse for OuterAttribute {261/// fn parse(input: ParseStream) -> Result<Self> {262/// let content;263/// Ok(OuterAttribute {264/// pound_token: input.parse()?,265/// bracket_token: bracketed!(content in input),266/// content: content.parse()?,267/// })268/// }269/// }270/// #271/// # fn main() {272/// # let input = quote! {273/// # #[repr(C, packed)]274/// # };275/// # syn::parse2::<OuterAttribute>(input).unwrap();276/// # }277/// ```278#[macro_export]279#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]280macro_rules! bracketed {281($content:ident in $cursor:expr) => {282match $crate::__private::parse_brackets(&$cursor) {283$crate::__private::Ok(brackets) => {284$content = brackets.content;285brackets.token286}287$crate::__private::Err(error) => {288return $crate::__private::Err(error);289}290}291};292}293294295