xref: /linux/rust/syn/group.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
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)]
parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>>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)]
parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>>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)]
parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>>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"))]
parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>>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 
parse_delimited<'a>( input: &ParseBuffer<'a>, delimiter: Delimiter, ) -> Result<(DelimSpan, ParseBuffer<'a>)>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