xref: /linux/rust/syn/group.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
1*69942c0aSMiguel Ojeda // SPDX-License-Identifier: Apache-2.0 OR MIT
2*69942c0aSMiguel Ojeda 
3808c999fSMiguel Ojeda use crate::error::Result;
4808c999fSMiguel Ojeda use crate::parse::ParseBuffer;
5808c999fSMiguel Ojeda use crate::token;
6808c999fSMiguel Ojeda use proc_macro2::extra::DelimSpan;
7808c999fSMiguel Ojeda use proc_macro2::Delimiter;
8808c999fSMiguel Ojeda 
9808c999fSMiguel Ojeda // Not public API.
10808c999fSMiguel Ojeda #[doc(hidden)]
11808c999fSMiguel Ojeda pub struct Parens<'a> {
12808c999fSMiguel Ojeda     #[doc(hidden)]
13808c999fSMiguel Ojeda     pub token: token::Paren,
14808c999fSMiguel Ojeda     #[doc(hidden)]
15808c999fSMiguel Ojeda     pub content: ParseBuffer<'a>,
16808c999fSMiguel Ojeda }
17808c999fSMiguel Ojeda 
18808c999fSMiguel Ojeda // Not public API.
19808c999fSMiguel Ojeda #[doc(hidden)]
20808c999fSMiguel Ojeda pub struct Braces<'a> {
21808c999fSMiguel Ojeda     #[doc(hidden)]
22808c999fSMiguel Ojeda     pub token: token::Brace,
23808c999fSMiguel Ojeda     #[doc(hidden)]
24808c999fSMiguel Ojeda     pub content: ParseBuffer<'a>,
25808c999fSMiguel Ojeda }
26808c999fSMiguel Ojeda 
27808c999fSMiguel Ojeda // Not public API.
28808c999fSMiguel Ojeda #[doc(hidden)]
29808c999fSMiguel Ojeda pub struct Brackets<'a> {
30808c999fSMiguel Ojeda     #[doc(hidden)]
31808c999fSMiguel Ojeda     pub token: token::Bracket,
32808c999fSMiguel Ojeda     #[doc(hidden)]
33808c999fSMiguel Ojeda     pub content: ParseBuffer<'a>,
34808c999fSMiguel Ojeda }
35808c999fSMiguel Ojeda 
36808c999fSMiguel Ojeda // Not public API.
37808c999fSMiguel Ojeda #[cfg(any(feature = "full", feature = "derive"))]
38808c999fSMiguel Ojeda #[doc(hidden)]
39808c999fSMiguel Ojeda pub struct Group<'a> {
40808c999fSMiguel Ojeda     #[doc(hidden)]
41808c999fSMiguel Ojeda     pub token: token::Group,
42808c999fSMiguel Ojeda     #[doc(hidden)]
43808c999fSMiguel Ojeda     pub content: ParseBuffer<'a>,
44808c999fSMiguel Ojeda }
45808c999fSMiguel Ojeda 
46808c999fSMiguel Ojeda // Not public API.
47808c999fSMiguel Ojeda #[doc(hidden)]
parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>>48808c999fSMiguel Ojeda pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
49808c999fSMiguel Ojeda     parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
50808c999fSMiguel Ojeda         token: token::Paren(span),
51808c999fSMiguel Ojeda         content,
52808c999fSMiguel Ojeda     })
53808c999fSMiguel Ojeda }
54808c999fSMiguel Ojeda 
55808c999fSMiguel Ojeda // Not public API.
56808c999fSMiguel Ojeda #[doc(hidden)]
parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>>57808c999fSMiguel Ojeda pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
58808c999fSMiguel Ojeda     parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
59808c999fSMiguel Ojeda         token: token::Brace(span),
60808c999fSMiguel Ojeda         content,
61808c999fSMiguel Ojeda     })
62808c999fSMiguel Ojeda }
63808c999fSMiguel Ojeda 
64808c999fSMiguel Ojeda // Not public API.
65808c999fSMiguel Ojeda #[doc(hidden)]
parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>>66808c999fSMiguel Ojeda pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
67808c999fSMiguel Ojeda     parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
68808c999fSMiguel Ojeda         token: token::Bracket(span),
69808c999fSMiguel Ojeda         content,
70808c999fSMiguel Ojeda     })
71808c999fSMiguel Ojeda }
72808c999fSMiguel Ojeda 
73808c999fSMiguel Ojeda #[cfg(any(feature = "full", feature = "derive"))]
parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>>74808c999fSMiguel Ojeda pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
75808c999fSMiguel Ojeda     parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
76808c999fSMiguel Ojeda         token: token::Group(span.join()),
77808c999fSMiguel Ojeda         content,
78808c999fSMiguel Ojeda     })
79808c999fSMiguel Ojeda }
80808c999fSMiguel Ojeda 
parse_delimited<'a>( input: &ParseBuffer<'a>, delimiter: Delimiter, ) -> Result<(DelimSpan, ParseBuffer<'a>)>81808c999fSMiguel Ojeda fn parse_delimited<'a>(
82808c999fSMiguel Ojeda     input: &ParseBuffer<'a>,
83808c999fSMiguel Ojeda     delimiter: Delimiter,
84808c999fSMiguel Ojeda ) -> Result<(DelimSpan, ParseBuffer<'a>)> {
85808c999fSMiguel Ojeda     input.step(|cursor| {
86808c999fSMiguel Ojeda         if let Some((content, span, rest)) = cursor.group(delimiter) {
87808c999fSMiguel Ojeda             let scope = span.close();
88808c999fSMiguel Ojeda             let nested = crate::parse::advance_step_cursor(cursor, content);
89808c999fSMiguel Ojeda             let unexpected = crate::parse::get_unexpected(input);
90808c999fSMiguel Ojeda             let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
91808c999fSMiguel Ojeda             Ok(((span, content), rest))
92808c999fSMiguel Ojeda         } else {
93808c999fSMiguel Ojeda             let message = match delimiter {
94808c999fSMiguel Ojeda                 Delimiter::Parenthesis => "expected parentheses",
95808c999fSMiguel Ojeda                 Delimiter::Brace => "expected curly braces",
96808c999fSMiguel Ojeda                 Delimiter::Bracket => "expected square brackets",
97808c999fSMiguel Ojeda                 Delimiter::None => "expected invisible group",
98808c999fSMiguel Ojeda             };
99808c999fSMiguel Ojeda             Err(cursor.error(message))
100808c999fSMiguel Ojeda         }
101808c999fSMiguel Ojeda     })
102808c999fSMiguel Ojeda }
103808c999fSMiguel Ojeda 
104808c999fSMiguel Ojeda /// Parse a set of parentheses and expose their content to subsequent parsers.
105808c999fSMiguel Ojeda ///
106808c999fSMiguel Ojeda /// # Example
107808c999fSMiguel Ojeda ///
108808c999fSMiguel Ojeda /// ```
109808c999fSMiguel Ojeda /// # use quote::quote;
110808c999fSMiguel Ojeda /// #
111808c999fSMiguel Ojeda /// use syn::{parenthesized, token, Ident, Result, Token, Type};
112808c999fSMiguel Ojeda /// use syn::parse::{Parse, ParseStream};
113808c999fSMiguel Ojeda /// use syn::punctuated::Punctuated;
114808c999fSMiguel Ojeda ///
115808c999fSMiguel Ojeda /// // Parse a simplified tuple struct syntax like:
116808c999fSMiguel Ojeda /// //
117808c999fSMiguel Ojeda /// //     struct S(A, B);
118808c999fSMiguel Ojeda /// struct TupleStruct {
119808c999fSMiguel Ojeda ///     struct_token: Token![struct],
120808c999fSMiguel Ojeda ///     ident: Ident,
121808c999fSMiguel Ojeda ///     paren_token: token::Paren,
122808c999fSMiguel Ojeda ///     fields: Punctuated<Type, Token![,]>,
123808c999fSMiguel Ojeda ///     semi_token: Token![;],
124808c999fSMiguel Ojeda /// }
125808c999fSMiguel Ojeda ///
126808c999fSMiguel Ojeda /// impl Parse for TupleStruct {
127808c999fSMiguel Ojeda ///     fn parse(input: ParseStream) -> Result<Self> {
128808c999fSMiguel Ojeda ///         let content;
129808c999fSMiguel Ojeda ///         Ok(TupleStruct {
130808c999fSMiguel Ojeda ///             struct_token: input.parse()?,
131808c999fSMiguel Ojeda ///             ident: input.parse()?,
132808c999fSMiguel Ojeda ///             paren_token: parenthesized!(content in input),
133808c999fSMiguel Ojeda ///             fields: content.parse_terminated(Type::parse, Token![,])?,
134808c999fSMiguel Ojeda ///             semi_token: input.parse()?,
135808c999fSMiguel Ojeda ///         })
136808c999fSMiguel Ojeda ///     }
137808c999fSMiguel Ojeda /// }
138808c999fSMiguel Ojeda /// #
139808c999fSMiguel Ojeda /// # fn main() {
140808c999fSMiguel Ojeda /// #     let input = quote! {
141808c999fSMiguel Ojeda /// #         struct S(A, B);
142808c999fSMiguel Ojeda /// #     };
143808c999fSMiguel Ojeda /// #     syn::parse2::<TupleStruct>(input).unwrap();
144808c999fSMiguel Ojeda /// # }
145808c999fSMiguel Ojeda /// ```
146808c999fSMiguel Ojeda #[macro_export]
147808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
148808c999fSMiguel Ojeda macro_rules! parenthesized {
149808c999fSMiguel Ojeda     ($content:ident in $cursor:expr) => {
150808c999fSMiguel Ojeda         match $crate::__private::parse_parens(&$cursor) {
151808c999fSMiguel Ojeda             $crate::__private::Ok(parens) => {
152808c999fSMiguel Ojeda                 $content = parens.content;
153808c999fSMiguel Ojeda                 parens.token
154808c999fSMiguel Ojeda             }
155808c999fSMiguel Ojeda             $crate::__private::Err(error) => {
156808c999fSMiguel Ojeda                 return $crate::__private::Err(error);
157808c999fSMiguel Ojeda             }
158808c999fSMiguel Ojeda         }
159808c999fSMiguel Ojeda     };
160808c999fSMiguel Ojeda }
161808c999fSMiguel Ojeda 
162808c999fSMiguel Ojeda /// Parse a set of curly braces and expose their content to subsequent parsers.
163808c999fSMiguel Ojeda ///
164808c999fSMiguel Ojeda /// # Example
165808c999fSMiguel Ojeda ///
166808c999fSMiguel Ojeda /// ```
167808c999fSMiguel Ojeda /// # use quote::quote;
168808c999fSMiguel Ojeda /// #
169808c999fSMiguel Ojeda /// use syn::{braced, token, Ident, Result, Token, Type};
170808c999fSMiguel Ojeda /// use syn::parse::{Parse, ParseStream};
171808c999fSMiguel Ojeda /// use syn::punctuated::Punctuated;
172808c999fSMiguel Ojeda ///
173808c999fSMiguel Ojeda /// // Parse a simplified struct syntax like:
174808c999fSMiguel Ojeda /// //
175808c999fSMiguel Ojeda /// //     struct S {
176808c999fSMiguel Ojeda /// //         a: A,
177808c999fSMiguel Ojeda /// //         b: B,
178808c999fSMiguel Ojeda /// //     }
179808c999fSMiguel Ojeda /// struct Struct {
180808c999fSMiguel Ojeda ///     struct_token: Token![struct],
181808c999fSMiguel Ojeda ///     ident: Ident,
182808c999fSMiguel Ojeda ///     brace_token: token::Brace,
183808c999fSMiguel Ojeda ///     fields: Punctuated<Field, Token![,]>,
184808c999fSMiguel Ojeda /// }
185808c999fSMiguel Ojeda ///
186808c999fSMiguel Ojeda /// struct Field {
187808c999fSMiguel Ojeda ///     name: Ident,
188808c999fSMiguel Ojeda ///     colon_token: Token![:],
189808c999fSMiguel Ojeda ///     ty: Type,
190808c999fSMiguel Ojeda /// }
191808c999fSMiguel Ojeda ///
192808c999fSMiguel Ojeda /// impl Parse for Struct {
193808c999fSMiguel Ojeda ///     fn parse(input: ParseStream) -> Result<Self> {
194808c999fSMiguel Ojeda ///         let content;
195808c999fSMiguel Ojeda ///         Ok(Struct {
196808c999fSMiguel Ojeda ///             struct_token: input.parse()?,
197808c999fSMiguel Ojeda ///             ident: input.parse()?,
198808c999fSMiguel Ojeda ///             brace_token: braced!(content in input),
199808c999fSMiguel Ojeda ///             fields: content.parse_terminated(Field::parse, Token![,])?,
200808c999fSMiguel Ojeda ///         })
201808c999fSMiguel Ojeda ///     }
202808c999fSMiguel Ojeda /// }
203808c999fSMiguel Ojeda ///
204808c999fSMiguel Ojeda /// impl Parse for Field {
205808c999fSMiguel Ojeda ///     fn parse(input: ParseStream) -> Result<Self> {
206808c999fSMiguel Ojeda ///         Ok(Field {
207808c999fSMiguel Ojeda ///             name: input.parse()?,
208808c999fSMiguel Ojeda ///             colon_token: input.parse()?,
209808c999fSMiguel Ojeda ///             ty: input.parse()?,
210808c999fSMiguel Ojeda ///         })
211808c999fSMiguel Ojeda ///     }
212808c999fSMiguel Ojeda /// }
213808c999fSMiguel Ojeda /// #
214808c999fSMiguel Ojeda /// # fn main() {
215808c999fSMiguel Ojeda /// #     let input = quote! {
216808c999fSMiguel Ojeda /// #         struct S {
217808c999fSMiguel Ojeda /// #             a: A,
218808c999fSMiguel Ojeda /// #             b: B,
219808c999fSMiguel Ojeda /// #         }
220808c999fSMiguel Ojeda /// #     };
221808c999fSMiguel Ojeda /// #     syn::parse2::<Struct>(input).unwrap();
222808c999fSMiguel Ojeda /// # }
223808c999fSMiguel Ojeda /// ```
224808c999fSMiguel Ojeda #[macro_export]
225808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
226808c999fSMiguel Ojeda macro_rules! braced {
227808c999fSMiguel Ojeda     ($content:ident in $cursor:expr) => {
228808c999fSMiguel Ojeda         match $crate::__private::parse_braces(&$cursor) {
229808c999fSMiguel Ojeda             $crate::__private::Ok(braces) => {
230808c999fSMiguel Ojeda                 $content = braces.content;
231808c999fSMiguel Ojeda                 braces.token
232808c999fSMiguel Ojeda             }
233808c999fSMiguel Ojeda             $crate::__private::Err(error) => {
234808c999fSMiguel Ojeda                 return $crate::__private::Err(error);
235808c999fSMiguel Ojeda             }
236808c999fSMiguel Ojeda         }
237808c999fSMiguel Ojeda     };
238808c999fSMiguel Ojeda }
239808c999fSMiguel Ojeda 
240808c999fSMiguel Ojeda /// Parse a set of square brackets and expose their content to subsequent
241808c999fSMiguel Ojeda /// parsers.
242808c999fSMiguel Ojeda ///
243808c999fSMiguel Ojeda /// # Example
244808c999fSMiguel Ojeda ///
245808c999fSMiguel Ojeda /// ```
246808c999fSMiguel Ojeda /// # use quote::quote;
247808c999fSMiguel Ojeda /// #
248808c999fSMiguel Ojeda /// use proc_macro2::TokenStream;
249808c999fSMiguel Ojeda /// use syn::{bracketed, token, Result, Token};
250808c999fSMiguel Ojeda /// use syn::parse::{Parse, ParseStream};
251808c999fSMiguel Ojeda ///
252808c999fSMiguel Ojeda /// // Parse an outer attribute like:
253808c999fSMiguel Ojeda /// //
254808c999fSMiguel Ojeda /// //     #[repr(C, packed)]
255808c999fSMiguel Ojeda /// struct OuterAttribute {
256808c999fSMiguel Ojeda ///     pound_token: Token![#],
257808c999fSMiguel Ojeda ///     bracket_token: token::Bracket,
258808c999fSMiguel Ojeda ///     content: TokenStream,
259808c999fSMiguel Ojeda /// }
260808c999fSMiguel Ojeda ///
261808c999fSMiguel Ojeda /// impl Parse for OuterAttribute {
262808c999fSMiguel Ojeda ///     fn parse(input: ParseStream) -> Result<Self> {
263808c999fSMiguel Ojeda ///         let content;
264808c999fSMiguel Ojeda ///         Ok(OuterAttribute {
265808c999fSMiguel Ojeda ///             pound_token: input.parse()?,
266808c999fSMiguel Ojeda ///             bracket_token: bracketed!(content in input),
267808c999fSMiguel Ojeda ///             content: content.parse()?,
268808c999fSMiguel Ojeda ///         })
269808c999fSMiguel Ojeda ///     }
270808c999fSMiguel Ojeda /// }
271808c999fSMiguel Ojeda /// #
272808c999fSMiguel Ojeda /// # fn main() {
273808c999fSMiguel Ojeda /// #     let input = quote! {
274808c999fSMiguel Ojeda /// #         #[repr(C, packed)]
275808c999fSMiguel Ojeda /// #     };
276808c999fSMiguel Ojeda /// #     syn::parse2::<OuterAttribute>(input).unwrap();
277808c999fSMiguel Ojeda /// # }
278808c999fSMiguel Ojeda /// ```
279808c999fSMiguel Ojeda #[macro_export]
280808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
281808c999fSMiguel Ojeda macro_rules! bracketed {
282808c999fSMiguel Ojeda     ($content:ident in $cursor:expr) => {
283808c999fSMiguel Ojeda         match $crate::__private::parse_brackets(&$cursor) {
284808c999fSMiguel Ojeda             $crate::__private::Ok(brackets) => {
285808c999fSMiguel Ojeda                 $content = brackets.content;
286808c999fSMiguel Ojeda                 brackets.token
287808c999fSMiguel Ojeda             }
288808c999fSMiguel Ojeda             $crate::__private::Err(error) => {
289808c999fSMiguel Ojeda                 return $crate::__private::Err(error);
290808c999fSMiguel Ojeda             }
291808c999fSMiguel Ojeda         }
292808c999fSMiguel Ojeda     };
293808c999fSMiguel Ojeda }
294