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}
283