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