blob: b0bc7cf04c0b60ed7c0eb8232d6807cf3acb06b4 [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 Layzell5bde96f2017-01-24 17:59:21 -050020 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, Some(o)),
21 $crate::IResult::Error => $crate::IResult::Done($i, None),
David Tolnayf6ccb832016-09-04 15:00:56 -070022 }
David Tolnayb5a7b142016-09-13 22:46:39 -070023 };
David Tolnayf6ccb832016-09-04 15:00:56 -070024
David Tolnayb5a7b142016-09-13 22:46:39 -070025 ($i:expr, $f:expr) => {
26 option!($i, call!($f));
27 };
28}
29
David Tolnay1f16b602017-02-07 20:06:55 -050030/// Turn a failed parse into an empty vector. The argument parser must itself
31/// return a vector.
Michael Layzell24645a32017-02-04 13:19:26 -050032///
David Tolnay1f16b602017-02-07 20:06:55 -050033/// This is often more convenient than `option!(...)` when the argument produces
34/// a vector.
Michael Layzell24645a32017-02-04 13:19:26 -050035///
36/// - **Syntax:** `opt_vec!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -050037/// - **Output:** `THING`, which must be `Vec<T>`
Michael Layzell24645a32017-02-04 13:19:26 -050038///
39/// ```rust
40/// extern crate syn;
41/// #[macro_use] extern crate synom;
42///
David Tolnay1f16b602017-02-07 20:06:55 -050043/// use syn::{Lifetime, Ty};
Alex Crichton954046c2017-05-30 21:49:42 -070044/// use syn::delimited::Delimited;
45/// use syn::tokens::*;
Michael Layzell24645a32017-02-04 13:19:26 -050046///
David Tolnay1f16b602017-02-07 20:06:55 -050047/// named!(bound_lifetimes -> (Vec<Lifetime>, Ty), tuple!(
48/// opt_vec!(do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -070049/// syn!(For) >>
50/// syn!(Lt) >>
51/// lifetimes: call!(Delimited::<Lifetime, Comma>::parse_terminated) >>
52/// syn!(Gt) >>
Alex Crichtonccbb45d2017-05-23 10:58:24 -070053/// (lifetimes.into_vec())
David Tolnay1f16b602017-02-07 20:06:55 -050054/// )),
Alex Crichton954046c2017-05-30 21:49:42 -070055/// syn!(Ty)
David Tolnay1f16b602017-02-07 20:06:55 -050056/// ));
Michael Layzell24645a32017-02-04 13:19:26 -050057///
Alex Crichton954046c2017-05-30 21:49:42 -070058/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -050059/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -050060#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070061macro_rules! opt_vec {
62 ($i:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb79ee962016-09-04 09:39:20 -070063 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050064 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, o),
65 $crate::IResult::Error => $crate::IResult::Done($i, Vec::new()),
David Tolnayb79ee962016-09-04 09:39:20 -070066 }
David Tolnayb5a7b142016-09-13 22:46:39 -070067 };
68}
David Tolnayb79ee962016-09-04 09:39:20 -070069
Michael Layzell24645a32017-02-04 13:19:26 -050070/// Parses nothing and always succeeds.
71///
David Tolnay1f16b602017-02-07 20:06:55 -050072/// This can be useful as a fallthrough case in `alt!`.
73///
Michael Layzell24645a32017-02-04 13:19:26 -050074/// - **Syntax:** `epsilon!()`
75/// - **Output:** `()`
76///
77/// ```rust
David Tolnay1f16b602017-02-07 20:06:55 -050078/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -050079/// #[macro_use] extern crate synom;
80///
David Tolnay1f16b602017-02-07 20:06:55 -050081/// use syn::Mutability;
Alex Crichton954046c2017-05-30 21:49:42 -070082/// use synom::tokens::Mut;
David Tolnay1f16b602017-02-07 20:06:55 -050083///
84/// named!(mutability -> Mutability, alt!(
Alex Crichton954046c2017-05-30 21:49:42 -070085/// syn!(Mut) => { Mutability::Mutable }
David Tolnay1f16b602017-02-07 20:06:55 -050086/// |
87/// epsilon!() => { |_| Mutability::Immutable }
88/// ));
Michael Layzell24645a32017-02-04 13:19:26 -050089///
Alex Crichton954046c2017-05-30 21:49:42 -070090/// # fn main() {}
Michael Layzell5bde96f2017-01-24 17:59:21 -050091#[macro_export]
David Tolnayb79ee962016-09-04 09:39:20 -070092macro_rules! epsilon {
93 ($i:expr,) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -050094 $crate::IResult::Done($i, ())
David Tolnayfa0edf22016-09-23 22:58:24 -070095 };
96}
97
Michael Layzell24645a32017-02-04 13:19:26 -050098/// Run a parser, binding the result to a name, and then evaluating an
99/// expression.
100///
101/// Discards the result of the expression and parser.
102///
103/// - **Syntax:** `tap!(NAME : THING => EXPR)`
104/// - **Output:** `()`
105///
106/// ```rust
107/// extern crate syn;
108/// #[macro_use] extern crate synom;
109///
Alex Crichton62a0a592017-05-22 13:58:53 -0700110/// use syn::{Expr, ExprCall};
Alex Crichton954046c2017-05-30 21:49:42 -0700111/// use syn::tokens::RArrow;
Michael Layzell24645a32017-02-04 13:19:26 -0500112///
David Tolnay1f16b602017-02-07 20:06:55 -0500113/// named!(expr_with_arrow_call -> Expr, do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -0700114/// mut e: syn!(Expr) >>
115/// many0!(tap!(arg: tuple!(syn!(RArrow), syn!(Expr)) => {
Michael Layzell24645a32017-02-04 13:19:26 -0500116/// e = Expr {
Alex Crichton62a0a592017-05-22 13:58:53 -0700117/// node: ExprCall {
118/// func: Box::new(e),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700119/// args: vec![arg.1].into(),
120/// paren_token: Default::default(),
Alex Crichton62a0a592017-05-22 13:58:53 -0700121/// }.into(),
Michael Layzell24645a32017-02-04 13:19:26 -0500122/// attrs: Vec::new(),
123/// };
124/// })) >>
125/// (e)
126/// ));
127///
Alex Crichton954046c2017-05-30 21:49:42 -0700128/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500129/// ```
David Tolnay1f16b602017-02-07 20:06:55 -0500130#[doc(hidden)]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500131#[macro_export]
David Tolnayfa0edf22016-09-23 22:58:24 -0700132macro_rules! tap {
133 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
134 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500135 $crate::IResult::Done(i, o) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700136 let $name = o;
137 $e;
Michael Layzell5bde96f2017-01-24 17:59:21 -0500138 $crate::IResult::Done(i, ())
David Tolnayfa0edf22016-09-23 22:58:24 -0700139 }
Michael Layzell5bde96f2017-01-24 17:59:21 -0500140 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayfa0edf22016-09-23 22:58:24 -0700141 }
142 };
143
144 ($i:expr, $name:ident : $f:expr => $e:expr) => {
145 tap!($i, $name: call!($f) => $e);
David Tolnayb79ee962016-09-04 09:39:20 -0700146 };
147}
Alex Crichton954046c2017-05-30 21:49:42 -0700148
149/// Parse a type through the `Synom` trait.
150///
151/// This is a convenience macro used to invoke the `Synom::parse` method for a
152/// type, you'll find this in quite a few parsers. This is also the primary way
153/// to parse punctuation.
154///
155/// - **Syntax:** `syn!(TYPE)`
156/// - **Output:** `TYPE`
157///
158/// ```rust
159/// extern crate syn;
160/// #[macro_use] extern crate synom;
161///
162/// use syn::Expr;
163/// use synom::tokens::Dot;
164///
165/// named!(expression -> Expr, syn!(Expr));
166///
167/// named!(expression_dot -> (Expr, Dot), tuple!(syn!(Expr), syn!(Dot)));
168///
169/// # fn main() {}
170/// ```
171#[macro_export]
172macro_rules! syn {
173 ($i:expr, $t:ty) => {
174 call!($i, <$t as $crate::Synom>::parse)
175 };
176}
177
178/// Parse a parenthesized-surrounded subtree.
179///
180/// This macro will invoke a sub-parser inside of all tokens contained in
181/// parenthesis. The sub-parser is required to consume all tokens within the
182/// parens or else this parser will return an error.
183///
184/// - **Syntax:** `parens!(SUBPARSER)`
185/// - **Output:** `(SUBPARSER_RET, Paren)`
186///
187/// ```rust
188/// extern crate syn;
189/// #[macro_use] extern crate synom;
190///
191/// use syn::Expr;
192/// use synom::tokens::Paren;
193///
194/// named!(expr_paren -> (Expr, Paren), parens!(syn!(Expr)));
195///
196/// # fn main() {}
197/// ```
198#[macro_export]
199macro_rules! parens {
200 ($i:expr, $submac:ident!( $($args:tt)* )) => {
201 $crate::tokens::Paren::parse($i, |i| $submac!(i, $($args)*))
202 };
203
204 ($i:expr, $f:expr) => {
205 parens!($i, call!($f));
206 };
207}
208
209
210/// Same as the `parens` macro, but for brackets.
211#[macro_export]
212macro_rules! brackets {
213 ($i:expr, $submac:ident!( $($args:tt)* )) => {
214 $crate::tokens::Bracket::parse($i, |i| $submac!(i, $($args)*))
215 };
216
217 ($i:expr, $f:expr) => {
218 brackets!($i, call!($f));
219 };
220}
221
222/// Same as the `parens` macro, but for braces.
223#[macro_export]
224macro_rules! braces {
225 ($i:expr, $submac:ident!( $($args:tt)* )) => {
226 $crate::tokens::Brace::parse($i, |i| $submac!(i, $($args)*))
227 };
228
229 ($i:expr, $f:expr) => {
230 braces!($i, call!($f));
231 };
232}