blob: 3872ed1671f1cc6028deccdc3a0f9beb208038ab [file] [log] [blame]
David Tolnay18c754c2018-08-21 23:26:58 -04001use proc_macro2::Delimiter;
2
David Tolnay544a90f2018-08-24 20:34:03 -04003use super::parse::{ParseBuffer, Result};
David Tolnay776f8e02018-08-24 22:32:10 -04004use token;
David Tolnay18c754c2018-08-21 23:26:58 -04005
6pub struct Braces<'a> {
7 pub token: token::Brace,
8 pub content: ParseBuffer<'a>,
9}
10
11impl<'a> ParseBuffer<'a> {
12 // Not public API.
13 #[doc(hidden)]
14 pub fn parse_braces(&self) -> Result<Braces<'a>> {
15 self.step_cursor(|cursor| {
16 if let Some((content, span, rest)) = cursor.group(Delimiter::Brace) {
17 let braces = Braces {
18 token: token::Brace(span),
19 content: ParseBuffer::new(span, cursor.advance(content)),
20 };
21 Ok((braces, rest))
22 } else {
23 Err(cursor.error("expected curly braces"))
24 }
25 })
26 }
27}
28
29/// Parse a set of curly braces and expose their content to subsequent parsers.
30///
31/// ```rust
David Tolnay6d67c742018-08-24 20:42:39 -040032/// # extern crate syn;
David Tolnay18c754c2018-08-21 23:26:58 -040033/// #
David Tolnay6d67c742018-08-24 20:42:39 -040034/// use syn::{braced, Token};
35/// use syn::next::{token, Ident};
36/// use syn::next::parse::{Parse, ParseStream, Result};
37/// #
38/// # mod example {
39/// # use super::{syn, braced, token, Ident, Parse, ParseStream, Result};
40/// #
41/// # macro_rules! Token {
42/// # (struct) => {
43/// # syn::next::token::Struct
44/// # };
45/// # }
46/// #
47/// # type Field = Ident;
David Tolnay18c754c2018-08-21 23:26:58 -040048///
49/// // Parse a simplified struct syntax like:
50/// //
51/// // struct S {
52/// // a: A,
53/// // b: B,
54/// // }
55/// struct Struct {
56/// pub struct_token: Token![struct],
57/// pub ident: Ident,
58/// pub brace_token: token::Brace,
59/// pub fields: Vec<Field>,
60/// }
61///
62/// impl Parse for Struct {
63/// fn parse(input: ParseStream) -> Result<Self> {
64/// let content;
65/// Ok(Struct {
66/// struct_token: input.parse()?,
67/// ident: input.parse()?,
68/// brace_token: braced!(content in input),
69/// fields: content.parse()?,
70/// })
71/// }
72/// }
David Tolnay6d67c742018-08-24 20:42:39 -040073/// # }
74/// #
75/// # fn main() {}
David Tolnay18c754c2018-08-21 23:26:58 -040076/// ```
77#[macro_export]
78macro_rules! braced {
79 ($content:ident in $cursor:expr) => {
David Tolnay544a90f2018-08-24 20:34:03 -040080 match $crate::next::parse::ParseBuffer::parse_braces(&$cursor) {
81 $crate::next::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -040082 $content = braces.content;
83 braces.token
84 }
David Tolnay544a90f2018-08-24 20:34:03 -040085 $crate::next::export::Err(error) => {
86 return $crate::next::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -040087 }
88 }
89 };
90}