use super::{Error, InputIter, Result};
pub fn not<I, O>(i: I, result: Result<I, O>) -> Result<I, ()>
where
I: InputIter,
{
match result {
Result::Complete(i, _) => Result::Fail(Error::new(
"Matched on input when we shouldn't have.",
Box::new(i.clone()),
)),
Result::Abort(e) => Result::Abort(e),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Fail(_) => Result::Complete(i, ()),
}
}
#[macro_export]
macro_rules! not {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {{
let _i = $i.clone();
$crate::combinators::not(_i, trap!($i.clone(), $f!($($args)*)))
}};
($i:expr, $f:ident( $( $args:tt )* ) ) => {
use $crate::run
$crate::not!($i, run!($f($($args)*)))
};
($i:expr, $f:ident) => {{
use $crate::run;
$crate::not!($i, run!($f))
}};
}
#[macro_export]
macro_rules! peek {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {{
use $crate::Result;
let _i = $i.clone();
match $f!(_i, $($args)*) {
Result::Complete(_, o) => Result::Complete($i, o),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Abort(e) => Result::Abort(e),
Result::Fail(e) => Result::Fail(e),
}
}};
($i:expr, $f:ident( $( $args:tt )* ) ) => {{
use $crate::run;
$crate::peek!($i, run!($f($($args)*)))
}};
($i:expr, $f:ident) => {{
use $crate::run;
$crate::peek!($i, run!($f))
}};
}
#[macro_export]
macro_rules! run {
($i:expr, $f:ident) => {
$f($i)
};
}
pub fn must<I, O>(result: Result<I, O>) -> Result<I, O>
where
I: InputIter,
{
match result {
Result::Complete(i, o) => Result::Complete(i, o),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Fail(e) => Result::Abort(e),
Result::Abort(e) => Result::Abort(e),
}
}
#[macro_export]
macro_rules! must {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {
$crate::combinators::must($f!($i, $($args)*))
};
($i:expr, $f:ident) => {{
use $crate::run;
$crate::must!($i, run!($f))
}};
}
#[macro_export]
macro_rules! with_err {
($i:expr, $f:ident!( $( $args:tt )* ), $e:expr) => {{
let _i = $i.clone();
match $f!($i, $($args)*) {
$crate::Result::Complete(i, o) => $crate::Result::Complete(i, o),
$crate::Result::Incomplete(ctx) => $crate::Result::Incomplete(ctx),
$crate::Result::Fail(e) => $crate::Result::Fail($crate::Error::new($e, Box::new(_i.clone()))),
$crate::Result::Abort(e) => $crate::Result::Abort($crate::Error::new($e, Box::new(_i.clone()))),
}
}};
($i:expr, $f:ident( $( $args:tt )* ), $e:expr ) => {{
use $crate::run;
$crate::with_err!($i, run!($f($($args)*)), $e:expr)
}};
($i:expr, $f:ident, $e:expr) => {{
use $crate::run;
$crate::with_err!($i, run!($f), $e)
}};
}
#[macro_export]
macro_rules! wrap_err {
($i:expr, $f:ident!( $( $args:tt )* ), $e:expr) => {{
let _i = $i.clone();
match $f!($i, $($args)*) {
$crate::Result::Complete(i, o) => $crate::Result::Complete(i, o),
$crate::Result::Incomplete(ctx) => $crate::Result::Incomplete(ctx),
$crate::Result::Fail(e) => $crate::Result::Fail($crate::Error::caused_by($e, Box::new(e), Box::new(_i.clone()))),
$crate::Result::Abort(e) => $crate::Result::Abort($crate::Error::caused_by($e, Box::new(e), Box::new(_i.clone()))),
}
}};
($i:expr, $f:ident( $( $args:tt )* ), $e:expr ) => {{
use $crate::run;
$crate::wrap_err!($i, run!($f($($args)*)), $e:expr)
}};
($i:expr, $f:ident, $e:expr) => {{
use $crate::run;
$crate::wrap_err!($i, run!($f), $e)
}};
}
pub fn trap<I, O>(result: Result<I, O>) -> Result<I, O>
where
I: InputIter,
{
match result {
Result::Complete(i, o) => Result::Complete(i, o),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Fail(e) => Result::Fail(e),
Result::Abort(e) => Result::Fail(e),
}
}
#[macro_export]
macro_rules! trap {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {
$crate::combinators::trap($f!($i, $($args)*))
};
($i:expr, $f:ident) => {{
use $crate::run;
$crate::trap!($i, run!($f))
}};
}
pub fn must_complete<I, O>(result: Result<I, O>, msg: String) -> Result<I, O>
where
I: InputIter,
{
match result {
Result::Complete(i, o) => Result::Complete(i, o),
Result::Incomplete(ctx) => Result::Abort(Error::new(msg, Box::new(ctx))),
Result::Fail(e) => Result::Abort(e),
Result::Abort(e) => Result::Abort(e),
}
}
pub fn complete<I, O, S>(result: Result<I, O>, msg: S) -> Result<I, O>
where
I: InputIter,
S: Into<String>,
{
match result {
Result::Incomplete(ctx) => Result::Fail(Error::new(msg.into(), Box::new(ctx))),
Result::Complete(i, o) => Result::Complete(i, o),
Result::Fail(e) => Result::Fail(e),
Result::Abort(e) => Result::Abort(e),
}
}
#[macro_export]
macro_rules! complete {
($i:expr, $e:expr, $f:ident!( $( $args:tt )* ) ) => {
$crate::combinators::complete($f!($i, $($args)*), $e)
};
($i:expr, $efn:expr, $f:ident) => {{
use $crate::run
$crate::complete!($i, $efn, run!($f))
}};
}
#[macro_export]
macro_rules! must_complete {
($i:expr, $e:expr, $f:ident!( $( $args:tt )* ) ) => {{
$crate::combinators::must_complete($f!($i.clone(), $($args)*), $e)
}};
($i:expr, $efn:expr, $f:ident) => {{
use $crate::run;
$crate::must_complete!($i, $efn, run!($f))
}};
}
#[macro_export]
macro_rules! do_each {
($i:expr, $val:ident => $f:ident) => {
$crate::compile_error!("do_each! must end with a tuple capturing the results")
};
($i:expr, $val:ident => $f:ident!($( $args:tt )* ), $($rest:tt)* ) => {
match $f!($i, $($args)*) {
$crate::Result::Complete(i, o) => {
let $val = o;
$crate::do_each!(i, $($rest)*)
}
$crate::Result::Incomplete(ctx) => {
$crate::Result::Incomplete(ctx)
}
$crate::Result::Fail(e) => $crate::Result::Fail(e),
$crate::Result::Abort(e) => $crate::Result::Abort(e),
}
};
($i:expr, _ => $f:ident!($( $args:tt )* ), $($rest:tt)* ) => {
match $f!($i, $($args)*) {
$crate::Result::Complete(i, _) => {
$crate::do_each!(i, $($rest)*)
}
$crate::Result::Incomplete(ctx) => {
$crate::Result::Incomplete(ctx)
}
$crate::Result::Fail(e) => $crate::Result::Fail(e),
$crate::Result::Abort(e) => $crate::Result::Abort(e),
}
};
($i:expr, $val:ident => $f:ident, $($rest:tt)* ) => {{
use $crate::run;
$crate::do_each!($i, $val => run!($f), $( $rest )* )
}};
($i:expr, _ => $f:ident, $($rest:tt)* ) => {{
use $crate::run;
$crate::do_each!($i, _ => run!($f), $( $rest )* )
}};
($i:expr, ( $($rest:tt)* ) ) => {
$crate::Result::Complete($i, ($($rest)*))
};
}
#[macro_export]
macro_rules! either {
($i:expr, $f:ident!( $( $args:tt )* ), $( $rest:tt)* ) => { $crate::either!(__impl $i, $f!( $($args)* ), $($rest)*)
};
($i:expr, $f:ident, $($rest:tt)* ) => {{ use $crate::run;
$crate::either!(__impl $i, run!($f), $($rest)*)
}};
($i:expr, $f:ident!( $( $args:tt )* )) => { $crate::compile_error!("Either requires at least two sub matchers.")
};
($i:expr, $f:ident) => {{ use $crate::run;
$crate::either!($i, run!($f))
}};
(__impl $i:expr, $f:ident) => {{ use $crate::run;
$crate::either!(__impl $i, run!($f))
}};
(__impl $i:expr, $f:ident,) => {{ use $crate::run;
$crate::either!(__impl $i, run!($f))
}};
(__impl $i:expr, $f:ident!( $( $args:tt )* ),) => { $crate::either!(__impl $i, $f!($($args)*) __end)
};
(__impl $i:expr, $f:ident!( $( $args:tt )* )) => {{ use $crate::Result;
match $f!($i, $($args)*) {
Result::Complete(i, o) => {
Result::Complete(i, o)
}
Result::Incomplete(ctx) => {
Result::Incomplete(ctx)
}
Result::Fail(e) => {
Result::Fail(e)
},
Result::Abort(e) => Result::Abort(e),
}
}};
(__impl $i:expr, $f:ident!( $( $args:tt )* ), $( $rest:tt )* ) => {{ use $crate::Result;
let _i = $i.clone();
match $f!($i, $($args)*) {
Result::Complete(i, o) => {
Result::Complete(i, o)
}
Result::Incomplete(ctx) => {
Result::Incomplete(ctx)
}
Result::Fail(_) => {
either!(__impl _i, $($rest)*)
},
Result::Abort(e) => Result::Abort(e),
}
}};
(__impl $i:expr, $f:ident, $( $rest:tt )* ) => {{ use $crate::run;
$crate::either!(__impl $i, run!($f), $( $rest )* )
}}
}
pub fn optional<I, O>(iter: I, result: Result<I, O>) -> Result<I, Option<O>>
where
I: InputIter,
{
match result {
Result::Complete(i, o) => Result::Complete(i, Some(o)),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Fail(_) => Result::Complete(iter, None),
Result::Abort(e) => Result::Abort(e),
}
}
#[macro_export]
macro_rules! optional {
($i:expr, $f:ident) => {{
use $crate::run;
$crate::optional!(__impl $i, run!($f))
}};
($i:expr, $f:ident!( $( $args:tt )* ) ) => {
$crate::optional!(__impl $i, $f!( $( $args )* ))
};
(__impl $i:expr, $f:ident!( $( $args:tt )* )) => {{
let _i = $i.clone();
$crate::combinators::optional(_i, $f!($i, $($args)*))
}};
}
#[macro_export]
macro_rules! repeat {
($i:expr, $f:ident!( $( $args:tt )* ) ) => {{
use $crate::Result;
let mut _i = $i.clone();
let mut seq = Vec::new();
let mut opt_error = None;
loop {
let __i = _i.clone();
match $f!(_i, $($args)*) {
Result::Complete(i, o) => {
seq.push(o);
_i = i;
}
Result::Abort(e) => {
opt_error = Some(Result::Abort(e));
_i = $i.clone();
break;
}
Result::Incomplete(_) => {
_i = __i;
break;
}
Result::Fail(_) => {
_i = __i;
break;
}
}
}
match opt_error {
Some(e) => e,
None => Result::Complete(_i, seq),
}
}};
($i:expr, $f:ident) => {{
use $crate::run;
$crate::repeat!($i, run!($f))
}};
}
#[macro_export]
macro_rules! separated {
($i:expr, $sep_rule:ident!( $( $sep_args:tt )* ), $item_rule:ident!( $( $item_args:tt )* ) ) => {{
use $crate::Result;
let _i = $i.clone();
let head = $item_rule!($i.clone(), $($item_args)*);
match head {
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Fail(e) => Result::Fail(e),
Result::Abort(e) => Result::Abort(e),
Result::Complete(i,item) => {
let mut list = vec![item];
let tail_result = repeat!(i,
do_each!(
_ => $sep_rule!($($sep_args)*),
item => $item_rule!($($item_args)*),
(item)
)
);
match tail_result {
Result::Fail(e) => Result::Fail(e),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Abort(e) => Result::Abort(e),
Result::Complete(i, mut tail) => {
list.extend(tail.drain(0..));
Result::Complete(i, list)
}
}
}
}
}};
($i:expr, $sep_rule:ident, $item_rule:ident ) => {{
use $crate::run;
$crate::separated!($i, run!($sep_rule), run!($item_rule))
}};
($i:expr, $sep_rule:ident!( $( $args:tt )* ), $item_rule:ident ) => {{
use $crate::run;
$crate::separated!($i, $sep_rule!($($args)*), run!($item_rule))
}};
($i:expr, $sep_rule:ident, $item_rule:ident!( $( $args:tt )* ) ) => {{
use $crate::run;
$crate::separated!($i, run!($sep_rule), $item_rule!($($args)*))
}};
}
#[macro_export]
macro_rules! text_token {
($i:expr, $e:expr) => {{
use $crate::Error;
use $crate::Result;
let mut _i = $i.clone();
let mut count = 0;
for expected in $e.bytes() {
let item = match _i.next() {
Some(item) => item,
None => break,
};
if item == &expected {
count += 1;
}
}
if count == $e.len() {
Result::Complete(_i.clone(), $e)
} else {
Result::Fail(Error::new(
format!("Expected {} but didn't get it.", $e),
Box::new($i.clone()),
))
}
}};
}
#[macro_export]
macro_rules! until {
($i:expr, $rule:ident!( $( $args:tt )* ) ) => {{
use $crate::{Result, Offsetable, Span, SpanRange};
let start_offset = $i.get_offset();
let mut _i = $i.clone();
let pfn = || {
loop {
match $rule!(_i.clone(), $($args)*) {
Result::Complete(_, _) => {
let range = SpanRange::Range(start_offset.._i.get_offset());
return Result::Complete(_i, $i.span(range));
},
Result::Abort(e) => return Result::Abort(e),
Result::Incomplete(ctx) => return Result::Incomplete(ctx),
Result::Fail(_) => {
}
}
if let None = _i.next() {
return Result::Incomplete(_i.clone());
}
}
};
pfn()
}};
($i:expr, $rule:ident) => {{
use $crate::run;
$crate::until!($i, run!($rule))
}};
}
#[macro_export]
macro_rules! discard {
($i:expr, $rule:ident) => {{
use $crate::run;
$crate::discard!($i, run!($rule))
}};
($i:expr, $rule:ident!( $( $args:tt )* ) ) => {{
use $crate::Result;
match $rule!($i, $($args)*) {
Result::Complete(i, _) => Result::Complete(i, ()),
Result::Incomplete(ctx) => Result::Incomplete(ctx),
Result::Fail(e) => Result::Fail(e),
Result::Abort(e) => Result::Abort(e),
}
}};
}
pub fn ascii_ws<'a, I: InputIter<Item = &'a u8>>(mut i: I) -> Result<I, u8> {
match i.next() {
Some(b) => {
if (*b as char).is_whitespace() {
Result::Complete(i, *b)
} else {
Result::Fail(Error::new(
"Not whitespace".to_string(),
Box::new(i.clone()),
))
}
}
None => Result::Fail(Error::new(
"Unexpected End Of Input".to_string(),
Box::new(i.clone()),
)),
}
}
pub fn eoi<I: InputIter>(i: I) -> Result<I, ()> {
let mut _i = i.clone();
match _i.next() {
Some(_) => Result::Fail(Error::new(
"Expected End Of Input".to_string(),
Box::new(i.clone()),
)),
None => Result::Complete(i, ()),
}
}
#[macro_export]
macro_rules! make_fn {
($name:ident<$i:ty, $o:ty>, $rule:ident!($( $body:tt )* )) => {
fn $name(i: $i) -> $crate::Result<$i, $o> {
$rule!(i, $($body)*)
}
};
(pub $name:ident<$i:ty, $o:ty>, $rule:ident!($( $body:tt )* )) => {
pub fn $name(i: $i) -> $crate::Result<$i, $o> {
$rule!(i, $($body)*)
}
};
($name:ident<$i:ty, $o:ty>, $rule:ident) => {
use $crate::run
$crate::make_fn!($name<$i, $o>, run!($rule));
};
(pub $name:ident<$i:ty, $o:ty>, $rule:ident) => {
use $crate::run
$crate::make_fn!(pub $name<$i, $o>, run!($rule));
};
}
#[macro_export]
macro_rules! input {
($i:expr) => {
$crate::input!($i,)
};
($i:expr,) => {{
let _i = $i.clone();
$crate::Result::Complete($i, _i)
}};
}
#[macro_export]
macro_rules! consume_all {
($i:expr, $rule:ident!( $( $args:tt )* ) ) => {{
use $crate::{Result, Offsetable, Span, SpanRange};
let start_offset = $i.get_offset();
let mut _i = $i.clone();
let pfn = || {
loop {
match $rule!(_i.clone(), $($args)*) {
Result::Complete(_, _) => {
},
Result::Abort(e) => return Result::Abort(e),
Result::Incomplete(ctx) => return Result::Incomplete(ctx),
Result::Fail(_) => {
let range = SpanRange::Range(start_offset.._i.get_offset());
return Result::Complete(_i, $i.span(range));
}
}
if let None = _i.next() {
return Result::Incomplete(_i.clone());
}
}
};
pfn()
}};
($i:expr, $rule:ident) => {{
use $crate::run;
$crate::consume_all!($i, run!($rule))
}}
}
#[inline(always)]
pub fn ascii_alphanumeric<'a, I: InputIter<Item = &'a u8>>(mut i: I) -> Result<I, u8> {
match i.next() {
Some(b) => {
let c = *b as char;
if c.is_ascii_alphabetic() || c.is_ascii_digit() {
Result::Complete(i, *b)
} else {
Result::Fail(Error::new(
"Not an alphanumeric character".to_string(),
Box::new(i.clone()),
))
}
}
None => Result::Fail(Error::new(
"Unexpected End Of Input.".to_string(),
Box::new(i.clone()),
)),
}
}
#[inline(always)]
pub fn ascii_digit<'a, I: InputIter<Item = &'a u8>>(mut i: I) -> Result<I, u8> {
match i.next() {
Some(b) => {
if (*b as char).is_ascii_digit() {
Result::Complete(i, *b)
} else {
Result::Fail(Error::new(
"Not an digit character".to_string(),
Box::new(i.clone()),
))
}
}
None => Result::Fail(Error::new(
"Unexpected End Of Input.".to_string(),
Box::new(i.clone()),
)),
}
}
#[inline(always)]
pub fn ascii_alpha<'a, I: InputIter<Item = &'a u8>>(mut i: I) -> Result<I, u8> {
match i.next() {
Some(b) => {
if (*b as char).is_ascii_alphabetic() {
Result::Complete(i, *b)
} else {
Result::Fail(Error::new(
"Not an alpha character".to_string(),
Box::new(i.clone()),
))
}
}
None => Result::Fail(Error::new(
"Unexpected End Of Input.".to_string(),
Box::new(i.clone()),
)),
}
}