blob: 9c44b7a235895d3caa19aa2a7d4447b3c25cbb2a [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 Tolnayb6254182018-08-25 08:44:54 -04004use 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 Tolnaya7d69fc2018-08-26 13:30:24 -040022pub struct Group<'a> {
23 pub token: token::Group,
24 pub content: ParseBuffer<'a>,
25}
26
David Tolnay18c754c2018-08-21 23:26:58 -040027impl<'a> ParseBuffer<'a> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040028 fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
David Tolnayb50c65a2018-08-30 21:14:57 -070029 self.step(|cursor| {
David Tolnay42342c82018-08-25 08:36:35 -040030 if let Some((content, span, rest)) = cursor.group(delimiter) {
David Tolnayeafc8052018-08-25 16:33:53 -040031 let content =
32 ParseBuffer::new(span, cursor.advance(content), self.get_unexpected());
David Tolnay42342c82018-08-25 08:36:35 -040033 Ok(((span, content), rest))
David Tolnay18c754c2018-08-21 23:26:58 -040034 } else {
David Tolnay42342c82018-08-25 08:36:35 -040035 let message = match delimiter {
36 Delimiter::Parenthesis => "expected parentheses",
37 Delimiter::Brace => "expected curly braces",
38 Delimiter::Bracket => "expected square brackets",
David Tolnaya7d69fc2018-08-26 13:30:24 -040039 Delimiter::None => "expected invisible group",
David Tolnay42342c82018-08-25 08:36:35 -040040 };
41 Err(cursor.error(message))
David Tolnay18c754c2018-08-21 23:26:58 -040042 }
43 })
44 }
David Tolnay42342c82018-08-25 08:36:35 -040045
46 // Not public API.
47 #[doc(hidden)]
48 pub fn parse_parens(&self) -> Result<Parens<'a>> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040049 self.parse_delimited(Delimiter::Parenthesis)
David Tolnay8c39ac52018-08-25 08:46:21 -040050 .map(|(span, content)| Parens {
51 token: token::Paren(span),
52 content: content,
53 })
David Tolnay42342c82018-08-25 08:36:35 -040054 }
55
56 // Not public API.
57 #[doc(hidden)]
58 pub fn parse_braces(&self) -> Result<Braces<'a>> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040059 self.parse_delimited(Delimiter::Brace)
David Tolnay8c39ac52018-08-25 08:46:21 -040060 .map(|(span, content)| Braces {
61 token: token::Brace(span),
62 content: content,
63 })
David Tolnay42342c82018-08-25 08:36:35 -040064 }
65
66 // Not public API.
67 #[doc(hidden)]
68 pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
David Tolnaya7d69fc2018-08-26 13:30:24 -040069 self.parse_delimited(Delimiter::Bracket)
David Tolnay8c39ac52018-08-25 08:46:21 -040070 .map(|(span, content)| Brackets {
71 token: token::Bracket(span),
72 content: content,
73 })
David Tolnay42342c82018-08-25 08:36:35 -040074 }
David Tolnaya7d69fc2018-08-26 13:30:24 -040075
76 // Not public API.
77 #[doc(hidden)]
78 pub fn parse_group(&self) -> Result<Group<'a>> {
79 self.parse_delimited(Delimiter::None)
80 .map(|(span, content)| Group {
81 token: token::Group(span),
82 content: content,
83 })
84 }
David Tolnay42342c82018-08-25 08:36:35 -040085}
86
87/// Parse a set of parentheses and expose their content to subsequent parsers.
88#[macro_export]
89macro_rules! parenthesized {
90 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -040091 match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -040092 $crate::export::Ok(parens) => {
93 $content = parens.content;
94 parens.token
95 }
96 $crate::export::Err(error) => {
97 return $crate::export::Err(error);
98 }
99 }
100 };
David Tolnay18c754c2018-08-21 23:26:58 -0400101}
102
103/// Parse a set of curly braces and expose their content to subsequent parsers.
104///
105/// ```rust
David Tolnay6d67c742018-08-24 20:42:39 -0400106/// # extern crate syn;
David Tolnay18c754c2018-08-21 23:26:58 -0400107/// #
David Tolnayb6254182018-08-25 08:44:54 -0400108/// use syn::{braced, token, Ident, Token};
109/// use syn::parse::{Parse, ParseStream, Result};
David Tolnaye7635332018-08-26 08:16:18 -0400110/// use syn::punctuated::Punctuated;
David Tolnay6d67c742018-08-24 20:42:39 -0400111/// #
David Tolnaye7635332018-08-26 08:16:18 -0400112/// # type Field = Ident;
David Tolnay18c754c2018-08-21 23:26:58 -0400113///
114/// // Parse a simplified struct syntax like:
115/// //
116/// // struct S {
117/// // a: A,
118/// // b: B,
119/// // }
120/// struct Struct {
121/// pub struct_token: Token![struct],
122/// pub ident: Ident,
123/// pub brace_token: token::Brace,
David Tolnaye7635332018-08-26 08:16:18 -0400124/// pub fields: Punctuated<Field, Token![,]>,
David Tolnay18c754c2018-08-21 23:26:58 -0400125/// }
126///
127/// impl Parse for Struct {
128/// fn parse(input: ParseStream) -> Result<Self> {
129/// let content;
130/// Ok(Struct {
131/// struct_token: input.parse()?,
132/// ident: input.parse()?,
133/// brace_token: braced!(content in input),
David Tolnaye7635332018-08-26 08:16:18 -0400134/// fields: content.parse_terminated(Field::parse)?,
David Tolnay18c754c2018-08-21 23:26:58 -0400135/// })
136/// }
137/// }
138/// ```
139#[macro_export]
140macro_rules! braced {
141 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400142 match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -0400143 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -0400144 $content = braces.content;
145 braces.token
146 }
David Tolnay456c9822018-08-25 08:09:46 -0400147 $crate::export::Err(error) => {
148 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -0400149 }
150 }
151 };
152}
David Tolnay42342c82018-08-25 08:36:35 -0400153
154/// Parse a set of square brackets and expose their content to subsequent
155/// parsers.
156#[macro_export]
157macro_rules! bracketed {
158 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400159 match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400160 $crate::export::Ok(brackets) => {
161 $content = brackets.content;
162 brackets.token
163 }
164 $crate::export::Err(error) => {
165 return $crate::export::Err(error);
166 }
167 }
168 };
169}
David Tolnaya7d69fc2018-08-26 13:30:24 -0400170
171#[doc(hidden)]
172#[macro_export]
173macro_rules! grouped {
174 ($content:ident in $cursor:expr) => {
175 match $crate::parse::ParseBuffer::parse_group(&$cursor) {
176 $crate::export::Ok(group) => {
177 $content = group.content;
178 group.token
179 }
180 $crate::export::Err(error) => {
181 return $crate::export::Err(error);
182 }
183 }
184 };
185}