1 use crate::error::Result; 2 use crate::parse::ParseBuffer; 3 use crate::token; 4 use proc_macro2::extra::DelimSpan; 5 use proc_macro2::Delimiter; 6 7 // Not public API. 8 #[doc(hidden)] 9 pub 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)] 18 pub 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)] 27 pub 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)] 37 pub 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)] 46 pub 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)] 55 pub 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)] 64 pub 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"))] 72 pub(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 79 fn 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 = span.close(); 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(docsrs, doc(cfg(feature = "parsing")))] 146 macro_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(docsrs, doc(cfg(feature = "parsing")))] 224 macro_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(docsrs, doc(cfg(feature = "parsing")))] 279 macro_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