blob: 923a41a4356179c8d5a77f1cb764979c05add16b [file] [log] [blame]
David Tolnay42342c82018-08-25 08:36:35 -04001use proc_macro2::{Delimiter, Span};
David Tolnay18c754c2018-08-21 23:26:58 -04002
David Tolnayad4b2472018-08-25 08:25:24 -04003use error::Result;
David Tolnayaa77a852018-08-31 11:15:10 -07004use parse::ParseBuffer;
5#[cfg(any(feature = "full", feature = "derive"))]
6use parse::ParseStream;
David Tolnay94f06632018-08-31 10:17:17 -07007use private;
David Tolnay776f8e02018-08-24 22:32:10 -04008use token;
David Tolnay18c754c2018-08-21 23:26:58 -04009
David Tolnay42342c82018-08-25 08:36:35 -040010pub struct Parens<'a> {
11 pub token: token::Paren,
12 pub content: ParseBuffer<'a>,
13}
14
David Tolnay18c754c2018-08-21 23:26:58 -040015pub struct Braces<'a> {
16 pub token: token::Brace,
17 pub content: ParseBuffer<'a>,
18}
19
David Tolnay42342c82018-08-25 08:36:35 -040020pub struct Brackets<'a> {
21 pub token: token::Bracket,
22 pub content: ParseBuffer<'a>,
23}
24
David Tolnayaa77a852018-08-31 11:15:10 -070025#[cfg(any(feature = "full", feature = "derive"))]
David Tolnaya7d69fc2018-08-26 13:30:24 -040026pub struct Group<'a> {
27 pub token: token::Group,
28 pub content: ParseBuffer<'a>,
29}
30
David Tolnay18c754c2018-08-21 23:26:58 -040031impl<'a> ParseBuffer<'a> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040032 fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
David Tolnayb50c65a2018-08-30 21:14:57 -070033 self.step(|cursor| {
David Tolnay42342c82018-08-25 08:36:35 -040034 if let Some((content, span, rest)) = cursor.group(delimiter) {
David Tolnay10951d52018-08-31 10:27:39 -070035 let unexpected = private::get_unexpected(self);
David Tolnay4ac232d2018-08-31 10:18:03 -070036 let content =
David Tolnay10951d52018-08-31 10:27:39 -070037 private::new_parse_buffer(span, cursor.advance(content), unexpected);
David Tolnay42342c82018-08-25 08:36:35 -040038 Ok(((span, content), rest))
David Tolnay18c754c2018-08-21 23:26:58 -040039 } else {
David Tolnay42342c82018-08-25 08:36:35 -040040 let message = match delimiter {
41 Delimiter::Parenthesis => "expected parentheses",
42 Delimiter::Brace => "expected curly braces",
43 Delimiter::Bracket => "expected square brackets",
David Tolnaya7d69fc2018-08-26 13:30:24 -040044 Delimiter::None => "expected invisible group",
David Tolnay42342c82018-08-25 08:36:35 -040045 };
46 Err(cursor.error(message))
David Tolnay18c754c2018-08-21 23:26:58 -040047 }
48 })
49 }
David Tolnay42342c82018-08-25 08:36:35 -040050
51 // Not public API.
52 #[doc(hidden)]
53 pub fn parse_parens(&self) -> Result<Parens<'a>> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040054 self.parse_delimited(Delimiter::Parenthesis)
David Tolnay8c39ac52018-08-25 08:46:21 -040055 .map(|(span, content)| Parens {
56 token: token::Paren(span),
57 content: content,
58 })
David Tolnay42342c82018-08-25 08:36:35 -040059 }
60
61 // Not public API.
62 #[doc(hidden)]
63 pub fn parse_braces(&self) -> Result<Braces<'a>> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040064 self.parse_delimited(Delimiter::Brace)
David Tolnay8c39ac52018-08-25 08:46:21 -040065 .map(|(span, content)| Braces {
66 token: token::Brace(span),
67 content: content,
68 })
David Tolnay42342c82018-08-25 08:36:35 -040069 }
70
71 // Not public API.
72 #[doc(hidden)]
73 pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040074 self.parse_delimited(Delimiter::Bracket)
David Tolnay8c39ac52018-08-25 08:46:21 -040075 .map(|(span, content)| Brackets {
76 token: token::Bracket(span),
77 content: content,
78 })
David Tolnay42342c82018-08-25 08:36:35 -040079 }
David Tolnayf57f76f2018-08-31 10:23:17 -070080}
David Tolnaya7d69fc2018-08-26 13:30:24 -040081
David Tolnayaa77a852018-08-31 11:15:10 -070082#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -070083impl private {
David Tolnayf57f76f2018-08-31 10:23:17 -070084 pub fn parse_group(input: ParseStream) -> Result<Group> {
85 input.parse_delimited(Delimiter::None)
David Tolnaya7d69fc2018-08-26 13:30:24 -040086 .map(|(span, content)| Group {
87 token: token::Group(span),
88 content: content,
89 })
90 }
David Tolnay42342c82018-08-25 08:36:35 -040091}
92
93/// Parse a set of parentheses and expose their content to subsequent parsers.
David Tolnay8bb9cca2018-09-01 01:50:19 -070094///
David Tolnay0e5a4cb2018-09-01 01:58:02 -070095/// # Example
96///
David Tolnay8bb9cca2018-09-01 01:50:19 -070097/// ```rust
98/// # #[macro_use]
99/// # extern crate quote;
100/// #
101/// extern crate syn;
102///
103/// use syn::{parenthesized, token, Ident, Token, Type};
104/// use syn::parse::{Parse, ParseStream, Result};
105/// use syn::punctuated::Punctuated;
106///
107/// // Parse a simplified tuple struct syntax like:
108/// //
109/// // struct S(A, B);
110/// struct TupleStruct {
111/// struct_token: Token![struct],
112/// ident: Ident,
113/// paren_token: token::Paren,
114/// fields: Punctuated<Type, Token![,]>,
115/// semi_token: Token![;],
116/// }
117///
118/// impl Parse for TupleStruct {
119/// fn parse(input: ParseStream) -> Result<Self> {
120/// let content;
121/// Ok(TupleStruct {
122/// struct_token: input.parse()?,
123/// ident: input.parse()?,
124/// paren_token: parenthesized!(content in input),
125/// fields: content.parse_terminated(Type::parse)?,
126/// semi_token: input.parse()?,
127/// })
128/// }
129/// }
130/// #
131/// # fn main() {
132/// # let input = quote! {
133/// # struct S(A, B);
134/// # };
135/// # syn::parse2::<TupleStruct>(input).unwrap();
136/// # }
137/// ```
David Tolnay42342c82018-08-25 08:36:35 -0400138#[macro_export]
139macro_rules! parenthesized {
140 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400141 match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400142 $crate::export::Ok(parens) => {
143 $content = parens.content;
144 parens.token
145 }
146 $crate::export::Err(error) => {
147 return $crate::export::Err(error);
148 }
149 }
150 };
David Tolnay18c754c2018-08-21 23:26:58 -0400151}
152
153/// Parse a set of curly braces and expose their content to subsequent parsers.
154///
David Tolnay0e5a4cb2018-09-01 01:58:02 -0700155/// # Example
156///
David Tolnay18c754c2018-08-21 23:26:58 -0400157/// ```rust
David Tolnay44962212018-09-01 01:41:44 -0700158/// # extern crate quote;
159/// # use quote::quote;
David Tolnay18c754c2018-08-21 23:26:58 -0400160/// #
David Tolnay44962212018-09-01 01:41:44 -0700161/// extern crate syn;
162///
163/// use syn::{braced, token, Ident, Token, Type};
David Tolnayb6254182018-08-25 08:44:54 -0400164/// use syn::parse::{Parse, ParseStream, Result};
David Tolnaye7635332018-08-26 08:16:18 -0400165/// use syn::punctuated::Punctuated;
David Tolnay18c754c2018-08-21 23:26:58 -0400166///
167/// // Parse a simplified struct syntax like:
168/// //
169/// // struct S {
170/// // a: A,
171/// // b: B,
172/// // }
173/// struct Struct {
David Tolnay44962212018-09-01 01:41:44 -0700174/// struct_token: Token![struct],
175/// ident: Ident,
176/// brace_token: token::Brace,
177/// fields: Punctuated<Field, Token![,]>,
178/// }
179///
180/// struct Field {
181/// name: Ident,
182/// colon_token: Token![:],
183/// ty: Type,
David Tolnay18c754c2018-08-21 23:26:58 -0400184/// }
185///
186/// impl Parse for Struct {
187/// fn parse(input: ParseStream) -> Result<Self> {
188/// let content;
189/// Ok(Struct {
190/// struct_token: input.parse()?,
191/// ident: input.parse()?,
192/// brace_token: braced!(content in input),
David Tolnaye7635332018-08-26 08:16:18 -0400193/// fields: content.parse_terminated(Field::parse)?,
David Tolnay18c754c2018-08-21 23:26:58 -0400194/// })
195/// }
196/// }
David Tolnay44962212018-09-01 01:41:44 -0700197///
198/// impl Parse for Field {
199/// fn parse(input: ParseStream) -> Result<Self> {
200/// Ok(Field {
201/// name: input.parse()?,
202/// colon_token: input.parse()?,
203/// ty: input.parse()?,
204/// })
205/// }
206/// }
207/// #
208/// # fn main() {
209/// # let input = quote! {
210/// # struct S {
211/// # a: A,
212/// # b: B,
213/// # }
214/// # };
215/// # syn::parse2::<Struct>(input).unwrap();
216/// # }
David Tolnay18c754c2018-08-21 23:26:58 -0400217/// ```
218#[macro_export]
219macro_rules! braced {
220 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400221 match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -0400222 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -0400223 $content = braces.content;
224 braces.token
225 }
David Tolnay456c9822018-08-25 08:09:46 -0400226 $crate::export::Err(error) => {
227 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -0400228 }
229 }
230 };
231}
David Tolnay42342c82018-08-25 08:36:35 -0400232
233/// Parse a set of square brackets and expose their content to subsequent
234/// parsers.
David Tolnay1d2960c2018-09-01 01:57:19 -0700235///
David Tolnay0e5a4cb2018-09-01 01:58:02 -0700236/// # Example
237///
David Tolnay1d2960c2018-09-01 01:57:19 -0700238/// ```rust
239/// # #[macro_use]
240/// # extern crate quote;
241/// #
242/// extern crate proc_macro2;
243/// extern crate syn;
244///
245/// use proc_macro2::TokenStream;
246/// use syn::{bracketed, token, Token};
247/// use syn::parse::{Parse, ParseStream, Result};
248///
249/// // Parse an outer attribute like:
250/// //
251/// // #[repr(C, packed)]
252/// struct OuterAttribute {
253/// pound_token: Token![#],
254/// bracket_token: token::Bracket,
255/// content: TokenStream,
256/// }
257///
258/// impl Parse for OuterAttribute {
259/// fn parse(input: ParseStream) -> Result<Self> {
260/// let content;
261/// Ok(OuterAttribute {
262/// pound_token: input.parse()?,
263/// bracket_token: bracketed!(content in input),
264/// content: content.parse()?,
265/// })
266/// }
267/// }
268/// #
269/// # fn main() {
270/// # let input = quote! {
271/// # #[repr(C, packed)]
272/// # };
273/// # syn::parse2::<OuterAttribute>(input).unwrap();
274/// # }
275/// ```
David Tolnay42342c82018-08-25 08:36:35 -0400276#[macro_export]
277macro_rules! bracketed {
278 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400279 match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400280 $crate::export::Ok(brackets) => {
281 $content = brackets.content;
282 brackets.token
283 }
284 $crate::export::Err(error) => {
285 return $crate::export::Err(error);
286 }
287 }
288 };
289}