blob: d04b8ba3e6f44c790e72c3ffa31f60fabd6c4b8a [file] [log] [blame]
David Tolnay1f16b602017-02-07 20:06:55 -05001/// Turn a failed parse into `None` and a successful parse into `Some`.
Michael Layzell24645a32017-02-04 13:19:26 -05002///
3/// - **Syntax:** `option!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -05004/// - **Output:** `Option<THING>`
Michael Layzell24645a32017-02-04 13:19:26 -05005///
6/// ```rust
7/// extern crate syn;
8/// #[macro_use] extern crate synom;
9///
Alex Crichton954046c2017-05-30 21:49:42 -070010/// use syn::tokens::Bang;
Michael Layzell24645a32017-02-04 13:19:26 -050011///
Alex Crichton954046c2017-05-30 21:49:42 -070012/// named!(maybe_bang -> Option<Bang>, option!(syn!(Bang)));
David Tolnay1f16b602017-02-07 20:06:55 -050013///
Alex Crichton954046c2017-05-30 21:49:42 -070014/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -050015/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -050016#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070017macro_rules! option {
18 ($i:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayf6ccb832016-09-04 15:00:56 -070019 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -040020 ::std::result::Result::Ok((i, o)) =>
21 ::std::result::Result::Ok((i, Some(o))),
22 ::std::result::Result::Err(_) =>
23 ::std::result::Result::Ok(($i, None)),
David Tolnayf6ccb832016-09-04 15:00:56 -070024 }
David Tolnayb5a7b142016-09-13 22:46:39 -070025 };
David Tolnayf6ccb832016-09-04 15:00:56 -070026
David Tolnayb5a7b142016-09-13 22:46:39 -070027 ($i:expr, $f:expr) => {
28 option!($i, call!($f));
29 };
30}
31
David Tolnay1f16b602017-02-07 20:06:55 -050032/// Turn a failed parse into an empty vector. The argument parser must itself
33/// return a vector.
Michael Layzell24645a32017-02-04 13:19:26 -050034///
David Tolnay1f16b602017-02-07 20:06:55 -050035/// This is often more convenient than `option!(...)` when the argument produces
36/// a vector.
Michael Layzell24645a32017-02-04 13:19:26 -050037///
38/// - **Syntax:** `opt_vec!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -050039/// - **Output:** `THING`, which must be `Vec<T>`
Michael Layzell24645a32017-02-04 13:19:26 -050040///
41/// ```rust
42/// extern crate syn;
43/// #[macro_use] extern crate synom;
44///
David Tolnay1f16b602017-02-07 20:06:55 -050045/// use syn::{Lifetime, Ty};
Alex Crichton954046c2017-05-30 21:49:42 -070046/// use syn::delimited::Delimited;
47/// use syn::tokens::*;
Michael Layzell24645a32017-02-04 13:19:26 -050048///
David Tolnay1f16b602017-02-07 20:06:55 -050049/// named!(bound_lifetimes -> (Vec<Lifetime>, Ty), tuple!(
50/// opt_vec!(do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -070051/// syn!(For) >>
52/// syn!(Lt) >>
53/// lifetimes: call!(Delimited::<Lifetime, Comma>::parse_terminated) >>
54/// syn!(Gt) >>
Alex Crichtonccbb45d2017-05-23 10:58:24 -070055/// (lifetimes.into_vec())
David Tolnay1f16b602017-02-07 20:06:55 -050056/// )),
Alex Crichton954046c2017-05-30 21:49:42 -070057/// syn!(Ty)
David Tolnay1f16b602017-02-07 20:06:55 -050058/// ));
Michael Layzell24645a32017-02-04 13:19:26 -050059///
Alex Crichton954046c2017-05-30 21:49:42 -070060/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -050061/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -050062#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070063macro_rules! opt_vec {
64 ($i:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb79ee962016-09-04 09:39:20 -070065 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -040066 ::std::result::Result::Ok((i, o)) =>
67 ::std::result::Result::Ok((i, o)),
68 ::std::result::Result::Err(_) =>
69 ::std::result::Result::Ok(($i, Vec::new()))
David Tolnayb79ee962016-09-04 09:39:20 -070070 }
David Tolnayb5a7b142016-09-13 22:46:39 -070071 };
72}
David Tolnayb79ee962016-09-04 09:39:20 -070073
Michael Layzell24645a32017-02-04 13:19:26 -050074/// Parses nothing and always succeeds.
75///
David Tolnay1f16b602017-02-07 20:06:55 -050076/// This can be useful as a fallthrough case in `alt!`.
77///
Michael Layzell24645a32017-02-04 13:19:26 -050078/// - **Syntax:** `epsilon!()`
79/// - **Output:** `()`
80///
81/// ```rust
David Tolnay1f16b602017-02-07 20:06:55 -050082/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -050083/// #[macro_use] extern crate synom;
84///
David Tolnay1f16b602017-02-07 20:06:55 -050085/// use syn::Mutability;
Alex Crichton954046c2017-05-30 21:49:42 -070086/// use synom::tokens::Mut;
David Tolnay1f16b602017-02-07 20:06:55 -050087///
88/// named!(mutability -> Mutability, alt!(
Alex Crichton954046c2017-05-30 21:49:42 -070089/// syn!(Mut) => { Mutability::Mutable }
David Tolnay1f16b602017-02-07 20:06:55 -050090/// |
91/// epsilon!() => { |_| Mutability::Immutable }
92/// ));
Michael Layzell24645a32017-02-04 13:19:26 -050093///
Alex Crichton954046c2017-05-30 21:49:42 -070094/// # fn main() {}
Michael Layzell5bde96f2017-01-24 17:59:21 -050095#[macro_export]
David Tolnayb79ee962016-09-04 09:39:20 -070096macro_rules! epsilon {
97 ($i:expr,) => {
Michael Layzell760fd662017-05-31 22:46:05 -040098 ::std::result::Result::Ok(($i, ()))
David Tolnayfa0edf22016-09-23 22:58:24 -070099 };
100}
101
Michael Layzell24645a32017-02-04 13:19:26 -0500102/// Run a parser, binding the result to a name, and then evaluating an
103/// expression.
104///
105/// Discards the result of the expression and parser.
106///
107/// - **Syntax:** `tap!(NAME : THING => EXPR)`
108/// - **Output:** `()`
109///
110/// ```rust
111/// extern crate syn;
112/// #[macro_use] extern crate synom;
113///
Alex Crichton62a0a592017-05-22 13:58:53 -0700114/// use syn::{Expr, ExprCall};
Alex Crichton954046c2017-05-30 21:49:42 -0700115/// use syn::tokens::RArrow;
Michael Layzell24645a32017-02-04 13:19:26 -0500116///
David Tolnay1f16b602017-02-07 20:06:55 -0500117/// named!(expr_with_arrow_call -> Expr, do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -0700118/// mut e: syn!(Expr) >>
119/// many0!(tap!(arg: tuple!(syn!(RArrow), syn!(Expr)) => {
Michael Layzell24645a32017-02-04 13:19:26 -0500120/// e = Expr {
Alex Crichton62a0a592017-05-22 13:58:53 -0700121/// node: ExprCall {
122/// func: Box::new(e),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700123/// args: vec![arg.1].into(),
124/// paren_token: Default::default(),
Alex Crichton62a0a592017-05-22 13:58:53 -0700125/// }.into(),
Michael Layzell24645a32017-02-04 13:19:26 -0500126/// attrs: Vec::new(),
127/// };
128/// })) >>
129/// (e)
130/// ));
131///
Alex Crichton954046c2017-05-30 21:49:42 -0700132/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500133/// ```
David Tolnay1f16b602017-02-07 20:06:55 -0500134#[doc(hidden)]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500135#[macro_export]
David Tolnayfa0edf22016-09-23 22:58:24 -0700136macro_rules! tap {
137 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
138 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400139 ::std::result::Result::Ok((i, o)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700140 let $name = o;
141 $e;
Michael Layzell760fd662017-05-31 22:46:05 -0400142 ::std::result::Result::Ok((i, ()))
David Tolnayfa0edf22016-09-23 22:58:24 -0700143 }
Michael Layzell760fd662017-05-31 22:46:05 -0400144 ::std::result::Result::Err(err) =>
145 ::std::result::Result::Err(err),
David Tolnayfa0edf22016-09-23 22:58:24 -0700146 }
147 };
148
149 ($i:expr, $name:ident : $f:expr => $e:expr) => {
150 tap!($i, $name: call!($f) => $e);
David Tolnayb79ee962016-09-04 09:39:20 -0700151 };
152}
Alex Crichton954046c2017-05-30 21:49:42 -0700153
154/// Parse a type through the `Synom` trait.
155///
156/// This is a convenience macro used to invoke the `Synom::parse` method for a
157/// type, you'll find this in quite a few parsers. This is also the primary way
158/// to parse punctuation.
159///
160/// - **Syntax:** `syn!(TYPE)`
161/// - **Output:** `TYPE`
162///
163/// ```rust
164/// extern crate syn;
165/// #[macro_use] extern crate synom;
166///
167/// use syn::Expr;
168/// use synom::tokens::Dot;
169///
170/// named!(expression -> Expr, syn!(Expr));
171///
172/// named!(expression_dot -> (Expr, Dot), tuple!(syn!(Expr), syn!(Dot)));
173///
174/// # fn main() {}
175/// ```
176#[macro_export]
177macro_rules! syn {
178 ($i:expr, $t:ty) => {
179 call!($i, <$t as $crate::Synom>::parse)
180 };
181}
182
183/// Parse a parenthesized-surrounded subtree.
184///
185/// This macro will invoke a sub-parser inside of all tokens contained in
186/// parenthesis. The sub-parser is required to consume all tokens within the
187/// parens or else this parser will return an error.
188///
189/// - **Syntax:** `parens!(SUBPARSER)`
190/// - **Output:** `(SUBPARSER_RET, Paren)`
191///
192/// ```rust
193/// extern crate syn;
194/// #[macro_use] extern crate synom;
195///
196/// use syn::Expr;
197/// use synom::tokens::Paren;
198///
199/// named!(expr_paren -> (Expr, Paren), parens!(syn!(Expr)));
200///
201/// # fn main() {}
202/// ```
203#[macro_export]
204macro_rules! parens {
205 ($i:expr, $submac:ident!( $($args:tt)* )) => {
206 $crate::tokens::Paren::parse($i, |i| $submac!(i, $($args)*))
207 };
208
209 ($i:expr, $f:expr) => {
210 parens!($i, call!($f));
211 };
212}
213
214
215/// Same as the `parens` macro, but for brackets.
216#[macro_export]
217macro_rules! brackets {
218 ($i:expr, $submac:ident!( $($args:tt)* )) => {
219 $crate::tokens::Bracket::parse($i, |i| $submac!(i, $($args)*))
220 };
221
222 ($i:expr, $f:expr) => {
223 brackets!($i, call!($f));
224 };
225}
226
227/// Same as the `parens` macro, but for braces.
228#[macro_export]
229macro_rules! braces {
230 ($i:expr, $submac:ident!( $($args:tt)* )) => {
231 $crate::tokens::Brace::parse($i, |i| $submac!(i, $($args)*))
232 };
233
234 ($i:expr, $f:expr) => {
235 braces!($i, call!($f));
236 };
237}