syn/
group.rs

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