syn/
group.rs

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