#[macro_export(local_inner_macros)]
macro_rules! wrap_sep (
  ($i:expr, $separator:expr, $submac:ident!( $($args:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::{Err,Convert,IResult};
    fn unify_types<I,O,P,E>(_: &IResult<I,O,E>, _: &IResult<I,P,E>) {}
    let sep_res = ($separator)($i);
    match sep_res {
      Ok((i1,_))    => {
        let res = $submac!(i1, $($args)*);
        unify_types(&sep_res, &res);
        res
      },
      Err(e) => Err(Err::convert(e)),
    }
  });
  ($i:expr, $separator:expr, $f:expr) => (
    wrap_sep!($i, $separator, call!($f))
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! pair_sep (
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    tuple!(
      $i,
      sep!($separator, $submac!($($args)*)),
      sep!($separator, $submac2!($($args2)*))
    )
  );
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
    pair_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
    pair_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:path, $f:expr, $g:expr) => (
    pair_sep!($i, $separator, call!($f), call!($g));
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! delimited_sep (
  ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
    use $crate::lib::std::result::Result::*;
    match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)*) {
      Err(e) => Err(e),
      Ok((remaining, (_,o,_))) => {
        Ok((remaining, o))
      }
    }
  });
  ($i:expr, $separator:path, $f:expr, $($rest:tt)+) => (
    delimited_sep!($i, $separator, call!($f), $($rest)*);
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! separated_pair_sep (
  ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
    use $crate::lib::std::result::Result::*;
    match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)*) {
      Err(e) => Err(e),
      Ok((remaining, (o1,_,o2))) => {
        Ok((remaining, (o1,o2)))
      }
    }
  });
  ($i:expr, $separator:path, $f:expr, $($rest:tt)+) => (
    separated_pair_sep!($i, $separator, call!($f), $($rest)*);
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! preceded_sep (
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
      Err(e) => Err(e),
      Ok((remaining, (_,o))) => {
        Ok((remaining, o))
      }
    }
  });
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
    preceded_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
    preceded_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:path, $f:expr, $g:expr) => (
    preceded_sep!($i, $separator, call!($f), call!($g));
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! terminated_sep (
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
      Err(e) => Err(e),
      Ok((remaining, (o,_))) => {
        Ok((remaining, o))
      }
    }
  });
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
    terminated_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
    terminated_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:path, $f:expr, $g:expr) => (
    terminated_sep!($i, $separator, call!($f), call!($g));
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! tuple_sep (
  ($i:expr, $separator:path, ($($parsed:tt),*), $e:path, $($rest:tt)*) => (
    tuple_sep!($i, $separator, ($($parsed),*), call!($e), $($rest)*);
  );
  ($i:expr, $separator:path, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(e) => Err(e),
        Ok((i,o))     => {
          tuple_sep!(i, $separator, (o), $($rest)*)
        }
      }
    }
  );
  ($i:expr, $separator:path, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(e) => Err(e),
        Ok((i,o))     => {
          tuple_sep!(i, $separator, ($($parsed)* , o), $($rest)*)
        }
      }
    }
  );
  ($i:expr, $separator:path, ($($parsed:tt),*), $e:path) => (
    tuple_sep!($i, $separator, ($($parsed),*), call!($e));
  );
  ($i:expr, $separator:path, (), $submac:ident!( $($args:tt)* )) => (
    {
      use $crate::lib::std::result::Result::*;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(e) => Err(e),
        Ok((i,o))     => {
          Ok((i, (o)))
        }
      }
    }
  );
  ($i:expr, $separator:path, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
    {
      use $crate::lib::std::result::Result::*;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(e) => Err(e),
        Ok((i,o))     => {
          Ok((i, ($($parsed),* , o)))
        }
      }
    }
  );
  ($i:expr, $separator:path, ($($parsed:expr),*)) => (
    {
      ::sts::result::Result::Ok(($i, ($($parsed),*)))
    }
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! do_parse_sep (
  (__impl $i:expr, $separator:path, ( $($rest:expr),* )) => (
    $crate::lib::std::result::Result::Ok(($i, ( $($rest),* )))
  );
  (__impl $i:expr, $separator:path, $e:ident >> $($rest:tt)*) => (
    do_parse_sep!(__impl $i, $separator, call!($e) >> $($rest)*);
  );
  (__impl $i:expr, $separator:path, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(e) => Err(e),
        Ok((i,_))     => {
          do_parse_sep!(__impl i, $separator, $($rest)*)
        },
      }
    }
  );
  (__impl $i:expr, $separator:path, $field:ident : $e:ident >> $($rest:tt)*) => (
    do_parse_sep!(__impl $i, $separator, $field: call!($e) >> $($rest)*);
  );
  (__impl $i:expr, $separator:path, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(e) => Err(e),
        Ok((i,o))     => {
          let $field = o;
          do_parse_sep!(__impl i, $separator, $($rest)*)
        },
      }
    }
  );
  
  (__impl $i:expr, $separator:path, $e:ident >> ( $($rest:tt)* )) => (
    do_parse_sep!(__impl $i, $separator, call!($e) >> ( $($rest)* ));
  );
  (__impl $i:expr, $separator:path, $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    match sep!($i, $separator, $submac!($($args)*)) {
      Err(e) => Err(e),
      Ok((i,_))     => {
        Ok((i, ( $($rest)* )))
      },
    }
  });
  (__impl $i:expr, $separator:path, $field:ident : $e:ident >> ( $($rest:tt)* )) => (
    do_parse_sep!(__impl $i, $separator, $field: call!($e) >> ( $($rest)* ) );
  );
  (__impl $i:expr, $separator:path, $field:ident : $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    match sep!($i, $separator, $submac!($($args)*)) {
      Err(e) => Err(e),
      Ok((i,o))     => {
        let $field = o;
        Ok((i, ( $($rest)* )))
      },
    }
  });
  ($i:expr, $separator:path, $($rest:tt)*) => (
    {
      do_parse_sep!(__impl $i, $separator, $($rest)*)
    }
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! permutation_sep (
  ($i:expr, $separator:path, $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::lib::std::option::Option::*;
      use $crate::{Err,ErrorKind,Convert};
      let mut res    = permutation_init!((), $($rest)*);
      let mut input  = $i;
      let mut error  = None;
      let mut needed = None;
      loop {
        let mut all_done = true;
        permutation_iterator_sep!(0, input, $separator, all_done, needed, res, $($rest)*);
        
        if !all_done {
          
          error = Option::Some(error_position!(input, ErrorKind::Permutation));
        }
        break;
      }
      if let Some(need) = needed {
        Err(Err::convert(need))
      } else {
        if let Some(unwrapped_res) = { permutation_unwrap!(0, (), res, $($rest)*) } {
          Ok((input, unwrapped_res))
        } else {
          if let Some(e) = error {
            Err(Err::Error(error_node_position!($i, ErrorKind::Permutation, e)))
          } else {
            Err(Err::Error(error_position!($i, ErrorKind::Permutation)))
          }
        }
      }
    }
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! permutation_iterator_sep (
  ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident?, $($rest:tt)*) => (
    permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, call!($e), $($rest)*);
  );
  ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident, $($rest:tt)*) => (
    permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, call!($e), $($rest)*);
  );
  ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => ({
    permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, $submac!($($args)*), $($rest)*);
  });
  ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::Err;
    if acc!($it, $res) == $crate::lib::std::option::Option::None {
      match {sep!($i, $separator, $submac!($($args)*))} {
        Ok((i,o))     => {
          $i = i;
          acc!($it, $res) = $crate::lib::std::option::Option::Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          $needed = $crate::lib::std::option::Option::Some(e);
          break;
        }
      };
    }
    succ!($it, permutation_iterator_sep!($i, $separator, $all_done, $needed, $res, $($rest)*));
  });
  ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident?) => (
    permutation_iterator_sep!($it, $i, $separator, $all_done, $res, call!($e));
  );
  ($it:tt,$i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $e:ident) => (
    permutation_iterator_sep!($it, $i, $separator, $all_done, $res, call!($e));
  );
  ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?) => ({
    permutation_iterator_sep!($it, $i, $separator, $all_done, $needed, $res, $submac!($($args)*));
  });
  ($it:tt, $i:expr, $separator:path, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::Err;
    if acc!($it, $res) == $crate::lib::std::option::Option::None {
      match sep!($i, $separator, $submac!($($args)*)) {
        Ok((i,o))     => {
          $i = i;
          acc!($it, $res) = $crate::lib::std::option::Option::Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          $needed = $crate::lib::std::option::Option::Some(e);
          break;
        }
      };
    }
  });
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! alt_sep (
  (__impl $i:expr, $separator:path, $e:path | $($rest:tt)*) => (
    alt_sep!(__impl $i, $separator, call!($e) | $($rest)*);
  );
  (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      let res = sep!($i, $separator, $subrule!($($args)*));
      match res {
        Ok((_,_))          => res,
        Err(Err::Error(_)) => alt_sep!(__impl $i, $separator, $($rest)*),
        Err(e)            => Err(e),
      }
    }
  );
  (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      match sep!($i, $separator, $subrule!( $($args)* )) {
        Ok((i,o))               => Ok((i,$gen(o))),
        Err(Err::Error(_))      => {
          alt_sep!(__impl $i, $separator, $($rest)*)
        },
        Err(e)            => Err(e),
      }
    }
  );
  (__impl $i:expr, $separator:path, $e:path => { $gen:expr } | $($rest:tt)*) => (
    alt_sep!(__impl $i, $separator, call!($e) => { $gen } | $($rest)*);
  );
  (__impl $i:expr, $separator:path, $e:path => { $gen:expr }) => (
    alt_sep!(__impl $i, $separator, call!($e) => { $gen });
  );
  (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      match sep!($i, $separator, $subrule!( $($args)* )) {
        Ok((i,o))     => Ok((i,$gen(o))),
        Err(Err::Error(e))      => {
          fn unify_types<T>(_: &T, _: &T) {}
          let e2 = error_position!($i, $crate::ErrorKind::Alt);
          unify_types(&e, &e2);
          Err(Err::Error(e2))
        },
        Err(e)            => Err(e),
      }
    }
  );
  (__impl $i:expr, $separator:path, $e:path) => (
    alt_sep!(__impl $i, $separator, call!($e));
  );
  (__impl $i:expr, $separator:path, $subrule:ident!( $($args:tt)*)) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      match sep!($i, $separator, $subrule!( $($args)* )) {
        Ok((i,o))     => Ok((i,o)),
        Err(Err::Error(e))      => {
          fn unify_types<T>(_: &T, _: &T) {}
          let e2 = error_position!($i, $crate::ErrorKind::Alt);
          unify_types(&e, &e2);
          Err(Err::Error(e2))
        },
        Err(e)            => Err(e),
      }
    }
  );
  (__impl $i:expr) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::{Err,Needed,IResult};
    Err(Err::Error(error_position!($i, $crate::ErrorKind::Alt)))
  });
  (__impl $i:expr, $separator:path) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::{Err,Needed,IResult};
    Err(Err::Error(error_position!($i, $crate::ErrorKind::Alt)))
  });
  ($i:expr, $separator:path, $($rest:tt)*) => (
    {
      alt_sep!(__impl $i, $separator, $($rest)*)
    }
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! alt_complete_sep (
  ($i:expr, $separator:path, $e:path | $($rest:tt)*) => (
    alt_complete_sep!($i, $separator, complete!(call!($e)) | $($rest)*);
  );
  ($i:expr, $separator:path, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      let res = complete!($i, sep!($separator, $subrule!($($args)*)));
      match res {
        Ok((_,_)) => res,
        _ => alt_complete_sep!($i, $separator, $($rest)*),
      }
    }
  );
  ($i:expr, $separator:path, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::{Err,Needed,IResult};
      match complete!($i, sep!($separator, $subrule!($($args)*))) {
        Ok((i,o)) => Ok((i,$gen(o))),
        _ => alt_complete_sep!($i, $separator, $($rest)*),
      }
    }
  );
  ($i:expr, $separator:path, $e:path => { $gen:expr } | $($rest:tt)*) => (
    alt_complete_sep!($i, $separator, complete!(call!($e)) => { $gen } | $($rest)*);
  );
  
  ($i:expr, $separator:path, $e:path => { $gen:expr }) => (
    alt_complete_sep!($i, $separator, call!($e) => { $gen });
  );
  ($i:expr, $separator:path, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => (
    alt_sep!(__impl $i, $separator, complete!($subrule!($($args)*)) => { $gen })
  );
  ($i:expr, $separator:path, $e:path) => (
    alt_complete_sep!($i, $separator, call!($e));
  );
  ($i:expr, $separator:path, $subrule:ident!( $($args:tt)*)) => (
    alt_sep!(__impl $i, $separator, complete!($subrule!($($args)*)))
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! switch_sep (
  (__impl $i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      match sep!($i, $separator, $submac!($($args)*)) {
        Err(Err::Error(e))      => Err(Err::Error(error_node_position!(
            $i, $crate::ErrorKind::Switch, e
        ))),
        Err(Err::Failure(e))    => Err(Err::Failure(
            error_node_position!($i, $crate::ErrorKind::Switch, e))),
        Err(e) => Err(e),
        Ok((i, o))    => {
          match o {
            $($p => match sep!(i, $separator, $subrule!($($args2)*)) {
              Err(Err::Error(e)) => Err(Err::Error(error_node_position!(
                  $i, $crate::ErrorKind::Switch, e
              ))),
              Err(Err::Failure(e))    => Err(Err::Failure(
                  error_node_position!($i, $crate::ErrorKind::Switch, e))),
              a => a,
            }),*,
            _    => Err(Err::Error(error_position!($i, $crate::ErrorKind::Switch)))
          }
        }
      }
    }
  );
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)*), $($rest:tt)*) => (
    {
      switch_sep!(__impl $i, $separator, $submac!($($args)*), $($rest)*)
    }
  );
  ($i:expr, $separator:path, $e:path, $($rest:tt)*) => (
    {
      switch_sep!(__impl $i, $separator, call!($e), $($rest)*)
    }
  );
);
#[doc(hidden)]
#[cfg(feature = "alloc")]
#[macro_export(local_inner_macros)]
macro_rules! separated_list_sep (
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    separated_list!(
      $i,
      sep!($separator, $submac!($($args)*)),
      sep!($separator, $submac2!($($args2)*))
    )
  );
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* ), $g:expr) => (
    separated_list_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:path, $f:expr, $submac:ident!( $($args:tt)* )) => (
    separated_list_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:path, $f:expr, $g:expr) => (
    separated_list_sep!($i, $separator, call!($f), call!($g));
  );
);
#[macro_export(local_inner_macros)]
macro_rules! eat_separator (
  ($i:expr, $arr:expr) => (
    {
      use $crate::{FindToken, InputTakeAtPosition};
      let input = $i;
      input.split_at_position(|c| !$arr.find_token(c))
    }
  );
);
#[macro_export(local_inner_macros)]
macro_rules! sep (
  ($i:expr,  $separator:path, tuple ! ($($rest:tt)*) ) => {
    tuple_sep!($i, $separator, (), $($rest)*)
  };
  ($i:expr,  $separator:path, pair ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      pair_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, delimited ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      delimited_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, separated_pair ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      separated_pair_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, preceded ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      preceded_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, terminated ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      terminated_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, do_parse ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      do_parse_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, permutation ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      permutation_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, alt ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      alt_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, alt_complete ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      alt_complete_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, switch ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      switch_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, separated_list ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      separated_list_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:path, many0 ! ($($rest:tt)*) ) => {
    many0!($i, wrap_sep!($separator, $($rest)*))
  };
  ($i:expr,  $separator:path, many1 ! ($($rest:tt)*) ) => {
    many1!($i, wrap_sep!($separator, $($rest)*))
  };
  ($i:expr, $separator:path, return_error!( $($args:tt)* )) => {
    return_error!($i, wrap_sep!($separator, $($args)*))
  };
  ($i:expr, $separator:path, $submac:ident!( $($args:tt)* )) => {
    wrap_sep!($i, $separator, $submac!($($args)*))
  };
  ($i:expr, $separator:path, $f:expr) => {
    wrap_sep!($i, $separator, call!($f))
  };
);
use internal::IResult;
use traits::{AsChar, FindToken, InputTakeAtPosition};
#[allow(unused_imports)]
pub fn sp<'a, T>(input: T) -> IResult<T, T>
where
  T: InputTakeAtPosition,
  <T as InputTakeAtPosition>::Item: AsChar + Clone,
  &'a str: FindToken<<T as InputTakeAtPosition>::Item>,
{
  input.split_at_position(|item| {
    let c = item.clone().as_char();
    !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
  })
  
  
}
#[macro_export(local_inner_macros)]
macro_rules! ws (
  ($i:expr, $($args:tt)*) => (
    {
      use $crate::sp;
      use $crate::Convert;
      use $crate::Err;
      use $crate::lib::std::result::Result::*;
      match sep!($i, sp, $($args)*) {
        Err(e) => Err(e),
        Ok((i1,o))    => {
          match (sp)(i1) {
            Err(e) => Err(Err::convert(e)),
            Ok((i2,_))    => Ok((i2, o))
          }
        }
      }
    }
  )
);
#[cfg(test)]
#[allow(dead_code)]
mod tests {
  #[cfg(feature = "alloc")]
  use lib::std::string::{String, ToString};
  use internal::{Err, IResult, Needed};
  use super::sp;
  use util::ErrorKind;
  use types::CompleteStr;
  #[test]
  fn spaaaaace() {
    assert_eq!(sp(&b" \t abc "[..]), Ok((&b"abc "[..], &b" \t "[..])));
  }
  #[test]
  fn tag() {
    named!(abc, ws!(tag!("abc")));
    assert_eq!(abc(&b" \t abc def"[..]), Ok((&b"def"[..], &b"abc"[..])));
  }
  #[test]
  fn pair() {
    named!(pair_2<&[u8], (&[u8], &[u8]) >,
      ws!(pair!( take!(3), tag!("de") ))
    );
    assert_eq!(
      pair_2(&b" \t abc de fg"[..]),
      Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
    );
  }
  #[test]
  fn preceded() {
    named!(prec<&[u8], &[u8] >,
      ws!(preceded!( take!(3), tag!("de") ))
    );
    assert_eq!(prec(&b" \t abc de fg"[..]), Ok((&b"fg"[..], &b"de"[..])));
  }
  #[test]
  fn terminated() {
    named!(term<&[u8], &[u8] >,
      ws!(terminated!( take!(3), tag!("de") ))
    );
    assert_eq!(term(&b" \t abc de fg"[..]), Ok((&b"fg"[..], &b"abc"[..])));
  }
  #[test]
  fn tuple() {
    
    named!(tuple_2<&[u8], (&[u8], &[u8]) >,
      ws!(tuple!( take!(3), tag!("de") ))
    );
    
    assert_eq!(
      tuple_2(&b" \t abc de fg"[..]),
      Ok((&b"fg"[..], (&b"abc"[..], &b"de"[..])))
    );
  }
  #[test]
  fn levels() {
    
    named!(level_2<&[u8], (&[u8], (&[u8], &[u8])) >,
      ws!(pair!(take!(3), tuple!( tag!("de"), tag!("fg ") )))
    );
    
    assert_eq!(
      level_2(&b" \t abc de fg \t hi "[..]),
      Ok((&b"hi "[..], (&b"abc"[..], (&b"de"[..], &b"fg "[..]))))
    );
  }
  #[test]
  fn do_parse() {
    fn ret_int1(i: &[u8]) -> IResult<&[u8], u8> {
      Ok((i, 1))
    };
    fn ret_int2(i: &[u8]) -> IResult<&[u8], u8> {
      Ok((i, 2))
    };
    
    named!(do_parser<&[u8], (u8, u8)>,
      ws!(do_parse!(
        tag!("abcd")       >>
        opt!(tag!("abcd")) >>
        aa: ret_int1       >>
        tag!("efgh")       >>
        bb: ret_int2       >>
        tag!("efgh")       >>
        (aa, bb)
      ))
    );
    
    assert_eq!(
      do_parser(&b"abcd abcd\tefghefghX"[..]),
      Ok((&b"X"[..], (1, 2)))
    );
    assert_eq!(
      do_parser(&b"abcd\tefgh      efgh X"[..]),
      Ok((&b"X"[..], (1, 2)))
    );
    assert_eq!(
      do_parser(&b"abcd  ab"[..]),
      Err(Err::Incomplete(Needed::Size(4)))
    );
    assert_eq!(
      do_parser(&b" abcd\tefgh\tef"[..]),
      Err(Err::Incomplete(Needed::Size(4)))
    );
  }
  #[test]
  fn permutation() {
    
    named!(
      perm<(&[u8], &[u8], &[u8])>,
      ws!(permutation!(tag!("abcd"), tag!("efg"), tag!("hi")))
    );
    
    let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
    let a = &b"abcd\tefg \thijk"[..];
    assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
    let b = &b"  efg  \tabcdhi jk"[..];
    assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
    let c = &b" hi   efg\tabcdjk"[..];
    assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
    let d = &b"efg  xyzabcdefghi"[..];
    assert_eq!(
      perm(d),
      Err(Err::Error(error_node_position!(
        &b"efg  xyzabcdefghi"[..],
        ErrorKind::Permutation,
        error_position!(&b"  xyzabcdefghi"[..], ErrorKind::Permutation)
      )))
    );
    let e = &b" efg \tabc"[..];
    assert_eq!(perm(e), Err(Err::Incomplete(Needed::Size(4))));
  }
  #[cfg(feature = "alloc")]
  #[derive(Debug, Clone, PartialEq)]
  pub struct ErrorStr(String);
  #[cfg(feature = "alloc")]
  impl From<u32> for ErrorStr {
    fn from(i: u32) -> Self {
      ErrorStr(format!("custom error code: {}", i))
    }
  }
  #[cfg(feature = "alloc")]
  impl<'a> From<&'a str> for ErrorStr {
    fn from(i: &'a str) -> Self {
      ErrorStr(format!("custom error message: {}", i))
    }
  }
  #[cfg(feature = "alloc")]
  #[test]
  fn alt() {
    fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      Ok((&b""[..], input))
    }
    #[allow(unused_variables)]
    fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      use Context;
      Err(Err::Error(Context::Code(
        &b""[..],
        ErrorKind::Custom(ErrorStr("abcd".to_string())),
      )))
    }
    fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      Ok((input, &b""[..]))
    }
    fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      alt!(i, dont_work | dont_work)
    }
    fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      alt!(i, dont_work | work)
    }
    fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      alt!(i, dont_work | dont_work | work2 | dont_work)
    }
    let a = &b"\tabcd"[..];
    assert_eq!(
      alt1(a),
      Err(Err::Error(error_position!(a, ErrorKind::Alt::<ErrorStr>)))
    );
    assert_eq!(alt2(a), Ok((&b""[..], a)));
    assert_eq!(alt3(a), Ok((a, &b""[..])));
    named!(alt4<CompleteStr, CompleteStr>, ws!(alt!(tag!("abcd") | tag!("efgh"))));
    assert_eq!(
      alt4(CompleteStr("\tabcd")),
      Ok((CompleteStr(""), CompleteStr(r"abcd")))
    );
    assert_eq!(
      alt4(CompleteStr("  efgh ")),
      Ok((CompleteStr(""), CompleteStr("efgh")))
    );
    
    named!(alt5<CompleteStr, bool>, ws!(alt!(tag!("abcd") => { |_| false } | tag!("efgh") => { |_| true })));
    assert_eq!(alt5(CompleteStr("\tabcd")), Ok((CompleteStr(""), false)));
    assert_eq!(alt5(CompleteStr("  efgh ")), Ok((CompleteStr(""), true)));
  }
  
  #[allow(unused_variables)]
  #[test]
  fn switch() {
    named!(sw<CompleteStr,CompleteStr>,
      ws!(switch!(take!(4),
        CompleteStr("abcd") => take!(2) |
        CompleteStr("efgh") => take!(4)
      ))
    );
    let a = CompleteStr(" abcd ef gh");
    assert_eq!(sw(a), Ok((CompleteStr("gh"), CompleteStr("ef"))));
    let b = CompleteStr("\tefgh ijkl ");
    assert_eq!(sw(b), Ok((CompleteStr(""), CompleteStr("ijkl"))));
    let c = CompleteStr("afghijkl");
    assert_eq!(
      sw(c),
      Err(Err::Error(error_position!(
        CompleteStr("afghijkl"),
        ErrorKind::Switch
      )))
    );
  }
  named!(str_parse(&str) -> &str, ws!(tag!("test")));
  #[allow(unused_variables)]
  #[test]
  fn str_test() {
    assert_eq!(str_parse(" \n   test\t a\nb"), Ok(("a\nb", "test")));
  }
  
  named!(space, tag!(" "));
  #[cfg(feature = "alloc")]
  named!(pipeline_statement<&[u8], ()>,
    ws!(
      do_parse!(
      tag!("pipeline") >>
      attributes: delimited!(char!('{'),
                             separated_list!(char!(','), alt!(
                               space |
                               space
                             )),
                             char!('}')) >>
      ({
        let _ = attributes;
        ()
      })
    )
  )
  );
  #[cfg(feature = "alloc")]
  named!(
    fail<&[u8]>,
    map!(many_till!(take!(1), ws!(tag!("."))), |(r, _)| r[0])
  );
}