blob: d04b8ba3e6f44c790e72c3ffa31f60fabd6c4b8a [file] [log] [blame]
/// Turn a failed parse into `None` and a successful parse into `Some`.
///
/// - **Syntax:** `option!(THING)`
/// - **Output:** `Option<THING>`
///
/// ```rust
/// extern crate syn;
/// #[macro_use] extern crate synom;
///
/// use syn::tokens::Bang;
///
/// named!(maybe_bang -> Option<Bang>, option!(syn!(Bang)));
///
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! option {
($i:expr, $submac:ident!( $($args:tt)* )) => {
match $submac!($i, $($args)*) {
::std::result::Result::Ok((i, o)) =>
::std::result::Result::Ok((i, Some(o))),
::std::result::Result::Err(_) =>
::std::result::Result::Ok(($i, None)),
}
};
($i:expr, $f:expr) => {
option!($i, call!($f));
};
}
/// Turn a failed parse into an empty vector. The argument parser must itself
/// return a vector.
///
/// This is often more convenient than `option!(...)` when the argument produces
/// a vector.
///
/// - **Syntax:** `opt_vec!(THING)`
/// - **Output:** `THING`, which must be `Vec<T>`
///
/// ```rust
/// extern crate syn;
/// #[macro_use] extern crate synom;
///
/// use syn::{Lifetime, Ty};
/// use syn::delimited::Delimited;
/// use syn::tokens::*;
///
/// named!(bound_lifetimes -> (Vec<Lifetime>, Ty), tuple!(
/// opt_vec!(do_parse!(
/// syn!(For) >>
/// syn!(Lt) >>
/// lifetimes: call!(Delimited::<Lifetime, Comma>::parse_terminated) >>
/// syn!(Gt) >>
/// (lifetimes.into_vec())
/// )),
/// syn!(Ty)
/// ));
///
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! opt_vec {
($i:expr, $submac:ident!( $($args:tt)* )) => {
match $submac!($i, $($args)*) {
::std::result::Result::Ok((i, o)) =>
::std::result::Result::Ok((i, o)),
::std::result::Result::Err(_) =>
::std::result::Result::Ok(($i, Vec::new()))
}
};
}
/// Parses nothing and always succeeds.
///
/// This can be useful as a fallthrough case in `alt!`.
///
/// - **Syntax:** `epsilon!()`
/// - **Output:** `()`
///
/// ```rust
/// extern crate syn;
/// #[macro_use] extern crate synom;
///
/// use syn::Mutability;
/// use synom::tokens::Mut;
///
/// named!(mutability -> Mutability, alt!(
/// syn!(Mut) => { Mutability::Mutable }
/// |
/// epsilon!() => { |_| Mutability::Immutable }
/// ));
///
/// # fn main() {}
#[macro_export]
macro_rules! epsilon {
($i:expr,) => {
::std::result::Result::Ok(($i, ()))
};
}
/// Run a parser, binding the result to a name, and then evaluating an
/// expression.
///
/// Discards the result of the expression and parser.
///
/// - **Syntax:** `tap!(NAME : THING => EXPR)`
/// - **Output:** `()`
///
/// ```rust
/// extern crate syn;
/// #[macro_use] extern crate synom;
///
/// use syn::{Expr, ExprCall};
/// use syn::tokens::RArrow;
///
/// named!(expr_with_arrow_call -> Expr, do_parse!(
/// mut e: syn!(Expr) >>
/// many0!(tap!(arg: tuple!(syn!(RArrow), syn!(Expr)) => {
/// e = Expr {
/// node: ExprCall {
/// func: Box::new(e),
/// args: vec![arg.1].into(),
/// paren_token: Default::default(),
/// }.into(),
/// attrs: Vec::new(),
/// };
/// })) >>
/// (e)
/// ));
///
/// # fn main() {}
/// ```
#[doc(hidden)]
#[macro_export]
macro_rules! tap {
($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
match $submac!($i, $($args)*) {
::std::result::Result::Ok((i, o)) => {
let $name = o;
$e;
::std::result::Result::Ok((i, ()))
}
::std::result::Result::Err(err) =>
::std::result::Result::Err(err),
}
};
($i:expr, $name:ident : $f:expr => $e:expr) => {
tap!($i, $name: call!($f) => $e);
};
}
/// Parse a type through the `Synom` trait.
///
/// This is a convenience macro used to invoke the `Synom::parse` method for a
/// type, you'll find this in quite a few parsers. This is also the primary way
/// to parse punctuation.
///
/// - **Syntax:** `syn!(TYPE)`
/// - **Output:** `TYPE`
///
/// ```rust
/// extern crate syn;
/// #[macro_use] extern crate synom;
///
/// use syn::Expr;
/// use synom::tokens::Dot;
///
/// named!(expression -> Expr, syn!(Expr));
///
/// named!(expression_dot -> (Expr, Dot), tuple!(syn!(Expr), syn!(Dot)));
///
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! syn {
($i:expr, $t:ty) => {
call!($i, <$t as $crate::Synom>::parse)
};
}
/// Parse a parenthesized-surrounded subtree.
///
/// This macro will invoke a sub-parser inside of all tokens contained in
/// parenthesis. The sub-parser is required to consume all tokens within the
/// parens or else this parser will return an error.
///
/// - **Syntax:** `parens!(SUBPARSER)`
/// - **Output:** `(SUBPARSER_RET, Paren)`
///
/// ```rust
/// extern crate syn;
/// #[macro_use] extern crate synom;
///
/// use syn::Expr;
/// use synom::tokens::Paren;
///
/// named!(expr_paren -> (Expr, Paren), parens!(syn!(Expr)));
///
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! parens {
($i:expr, $submac:ident!( $($args:tt)* )) => {
$crate::tokens::Paren::parse($i, |i| $submac!(i, $($args)*))
};
($i:expr, $f:expr) => {
parens!($i, call!($f));
};
}
/// Same as the `parens` macro, but for brackets.
#[macro_export]
macro_rules! brackets {
($i:expr, $submac:ident!( $($args:tt)* )) => {
$crate::tokens::Bracket::parse($i, |i| $submac!(i, $($args)*))
};
($i:expr, $f:expr) => {
brackets!($i, call!($f));
};
}
/// Same as the `parens` macro, but for braces.
#[macro_export]
macro_rules! braces {
($i:expr, $submac:ident!( $($args:tt)* )) => {
$crate::tokens::Brace::parse($i, |i| $submac!(i, $($args)*))
};
($i:expr, $f:expr) => {
braces!($i, call!($f));
};
}