1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 use crate::error::Result; 4 use crate::parse::ParseBuffer; 5 use crate::token; 6 use proc_macro2::extra::DelimSpan; 7 use proc_macro2::Delimiter; 8 9 // Not public API. 10 #[doc(hidden)] 11 pub 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)] 20 pub 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)] 29 pub 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)] 39 pub 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)] 48 pub 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)] 57 pub 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)] 66 pub 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"))] 74 pub(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 81 fn 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")))] 148 macro_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")))] 226 macro_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")))] 281 macro_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 } 294