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