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