1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
#![allow(unused_imports)]

use ::token::Id;
use ::slice::TkSlice;
use traits::redefs_nom::InputLengthRedef;

/// Generalized form of nom's `eat_seperator!` macro
///
/// helper macros to build a separator parser
///
/// ```ignore
/// #[macro_use] extern crate nom;
/// use nom::IResult::Done;
///
/// named!(pub consume_spaces_and_tabs, drop_tokens!(&[Id::Space, Id::Tab]));
/// fn main() {}
/// ```
#[macro_export]
macro_rules! drop_tokens (
      ($i:expr, $arr:expr) => (
        {
          use nom;
          use nom::{InputLength,InputIter,Slice,FindToken};
          if ($i).input_len() == 0 {
            nom::IResult::Done(($i).slice(0..), ($i).slice(0..0))
          } else {
            match ($i).iter_indices().map(|(j, item)| {
                (j, item.find_token($arr))
               })
                .filter(|&(_, is_token)| !is_token)
                .map(|(j, _)| j)
                .next() {
              ::std::option::Option::Some(index) => {
                nom::IResult::Done(($i).slice(index..), ($i).slice(..index))
              },
              ::std::option::Option::None        => {
                nom::IResult::Done(($i).slice(($i).input_len()..), ($i))
              }
            }
          }
        }
      );
    );


/// Redef of the `ws!()` macro from `nom` for filtering based on `Tk::id()` instead of a bytes.
/// Ignores spaces, tabs, and other whitespace for the scope of the wrapped subparser.
///
#[macro_export]
macro_rules! ignore_spaces (
  ($i:expr, $($args:tt)*) => (
    {
      use $crate::util::filter_non_critical_python_whitespace;
      sep!($i, filter_non_critical_python_whitespace, $($args)*)
    }
  )
);


/// Matches one of the provided tokens.
///
/// Generalized form of nom's `one_of!` macro.
#[macro_export]
macro_rules! tk_is_one_of (
    ($i:expr, $inp: expr) => (
        {
          use nom::Slice;
          use nom::AsChar;
          use nom::FindToken;
          use nom::InputIter;

          match ($i).iter_elements().next().map(|c| {
            c.find_token($inp)
          }) {
            None        => nom::IResult::Incomplete::<_, _>(nom::Needed::Size(1)),
            Some(false) => nom::IResult::Error(error_position!(nom::ErrorKind::OneOf, $i)),
            //the unwrap should be safe here
            Some(true)  => nom::IResult::Done($i.slice(1..), $i.iter_elements().next().unwrap())
          }
        }
    );
);


/// Matches one of the provided tokens.
///
/// Generalized form of nom's `none_of!` macro. which just takes the .as_char() off
/// of the `Some(true)` case in order to return back the whatever is produced by
/// the slice.
#[macro_export]
macro_rules! tk_is_none_of (
  ($i:expr, $inp: expr) => (
    {
      use nom::Slice;
      use nom::AsChar;
      use nom::FindToken;
      use nom::InputIter;
      use $crate::slice::TkSlice;

      match ($i).iter_elements().next().map(|c| {
        !c.find_token($inp)
      }) {
        None        => nom::IResult::Incomplete::<_, _>(nom::Needed::Size(1)),
        Some(false) => nom::IResult::Error(error_position!(nom::ErrorKind::NoneOf, $i)),
        //the unwrap should be safe here
        Some(true)  => nom::IResult::Done($i.slice(1..), $i.slice(..1))
      }
    }
  );
);