blob: 77a9cc6170e857b9da6468133bb890ae8432271b [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 Tolnay7c6f21b2018-08-25 08:28:55 -04004use next::parse::ParseBuffer;
David Tolnay776f8e02018-08-24 22:32:10 -04005use token;
David Tolnay18c754c2018-08-21 23:26:58 -04006
David Tolnay42342c82018-08-25 08:36:35 -04007pub struct Parens<'a> {
8 pub token: token::Paren,
9 pub content: ParseBuffer<'a>,
10}
11
David Tolnay18c754c2018-08-21 23:26:58 -040012pub struct Braces<'a> {
13 pub token: token::Brace,
14 pub content: ParseBuffer<'a>,
15}
16
David Tolnay42342c82018-08-25 08:36:35 -040017pub struct Brackets<'a> {
18 pub token: token::Bracket,
19 pub content: ParseBuffer<'a>,
20}
21
David Tolnay18c754c2018-08-21 23:26:58 -040022impl<'a> ParseBuffer<'a> {
David Tolnay42342c82018-08-25 08:36:35 -040023 fn parse_group(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
David Tolnay18c754c2018-08-21 23:26:58 -040024 self.step_cursor(|cursor| {
David Tolnay42342c82018-08-25 08:36:35 -040025 if let Some((content, span, rest)) = cursor.group(delimiter) {
26 let content = ParseBuffer::new(span, cursor.advance(content));
27 Ok(((span, content), rest))
David Tolnay18c754c2018-08-21 23:26:58 -040028 } else {
David Tolnay42342c82018-08-25 08:36:35 -040029 let message = match delimiter {
30 Delimiter::Parenthesis => "expected parentheses",
31 Delimiter::Brace => "expected curly braces",
32 Delimiter::Bracket => "expected square brackets",
33 Delimiter::None => unreachable!(),
34 };
35 Err(cursor.error(message))
David Tolnay18c754c2018-08-21 23:26:58 -040036 }
37 })
38 }
David Tolnay42342c82018-08-25 08:36:35 -040039
40 // Not public API.
41 #[doc(hidden)]
42 pub fn parse_parens(&self) -> Result<Parens<'a>> {
43 self.parse_group(Delimiter::Parenthesis).map(|(span, content)| Parens {
44 token: token::Paren(span),
45 content: content,
46 })
47 }
48
49 // Not public API.
50 #[doc(hidden)]
51 pub fn parse_braces(&self) -> Result<Braces<'a>> {
52 self.parse_group(Delimiter::Brace).map(|(span, content)| Braces {
53 token: token::Brace(span),
54 content: content,
55 })
56 }
57
58 // Not public API.
59 #[doc(hidden)]
60 pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
61 self.parse_group(Delimiter::Bracket).map(|(span, content)| Brackets {
62 token: token::Bracket(span),
63 content: content,
64 })
65 }
66}
67
68/// Parse a set of parentheses and expose their content to subsequent parsers.
69#[macro_export]
70macro_rules! parenthesized {
71 ($content:ident in $cursor:expr) => {
72 match $crate::next::parse::ParseBuffer::parse_parens(&$cursor) {
73 $crate::export::Ok(parens) => {
74 $content = parens.content;
75 parens.token
76 }
77 $crate::export::Err(error) => {
78 return $crate::export::Err(error);
79 }
80 }
81 };
David Tolnay18c754c2018-08-21 23:26:58 -040082}
83
84/// Parse a set of curly braces and expose their content to subsequent parsers.
85///
86/// ```rust
David Tolnay6d67c742018-08-24 20:42:39 -040087/// # extern crate syn;
David Tolnay18c754c2018-08-21 23:26:58 -040088/// #
David Tolnay6d67c742018-08-24 20:42:39 -040089/// use syn::{braced, Token};
90/// use syn::next::{token, Ident};
91/// use syn::next::parse::{Parse, ParseStream, Result};
92/// #
93/// # mod example {
94/// # use super::{syn, braced, token, Ident, Parse, ParseStream, Result};
95/// #
96/// # macro_rules! Token {
97/// # (struct) => {
98/// # syn::next::token::Struct
99/// # };
100/// # }
101/// #
102/// # type Field = Ident;
David Tolnay18c754c2018-08-21 23:26:58 -0400103///
104/// // Parse a simplified struct syntax like:
105/// //
106/// // struct S {
107/// // a: A,
108/// // b: B,
109/// // }
110/// struct Struct {
111/// pub struct_token: Token![struct],
112/// pub ident: Ident,
113/// pub brace_token: token::Brace,
114/// pub fields: Vec<Field>,
115/// }
116///
117/// impl Parse for Struct {
118/// fn parse(input: ParseStream) -> Result<Self> {
119/// let content;
120/// Ok(Struct {
121/// struct_token: input.parse()?,
122/// ident: input.parse()?,
123/// brace_token: braced!(content in input),
124/// fields: content.parse()?,
125/// })
126/// }
127/// }
David Tolnay6d67c742018-08-24 20:42:39 -0400128/// # }
129/// #
130/// # fn main() {}
David Tolnay18c754c2018-08-21 23:26:58 -0400131/// ```
132#[macro_export]
133macro_rules! braced {
134 ($content:ident in $cursor:expr) => {
David Tolnay544a90f2018-08-24 20:34:03 -0400135 match $crate::next::parse::ParseBuffer::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -0400136 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -0400137 $content = braces.content;
138 braces.token
139 }
David Tolnay456c9822018-08-25 08:09:46 -0400140 $crate::export::Err(error) => {
141 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -0400142 }
143 }
144 };
145}
David Tolnay42342c82018-08-25 08:36:35 -0400146
147/// Parse a set of square brackets and expose their content to subsequent
148/// parsers.
149#[macro_export]
150macro_rules! bracketed {
151 ($content:ident in $cursor:expr) => {
152 match $crate::next::parse::ParseBuffer::parse_brackets(&$cursor) {
153 $crate::export::Ok(brackets) => {
154 $content = brackets.content;
155 brackets.token
156 }
157 $crate::export::Err(error) => {
158 return $crate::export::Err(error);
159 }
160 }
161 };
162}