diff --git a/src/macros.rs b/src/macros.rs index 8f96cc5..fbdf92b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,5 +1,31 @@ //! Contains the helper macros for abortable-parser. +/// Convenience macro for looking for a specific text token in a byte input stream. +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), $i)) + } + }}; +} + +// FIXME(jwall): We need until!, not! and peek!. + /// Converts a function indentifier into a macro call. Useful when writing your own macro combinator. #[macro_export] macro_rules! run { @@ -25,6 +51,8 @@ macro_rules! must { }; } +/// Wraps any Error return from a subparser in another error. Stores the position at +/// this point in the parse tree allowing you to associate context with wrapped errors. #[macro_export] macro_rules! wrap_err { ($i:expr, $f:ident!( $( $args:tt )* ), $e:expr) => {{ diff --git a/src/test.rs b/src/test.rs index 5b74f6a..40937c5 100644 --- a/src/test.rs +++ b/src/test.rs @@ -66,6 +66,26 @@ fn parse_three(i: SliceIter) -> Result, String, String> { } } +#[test] +fn test_text_token() { + let input_str = "foo bar"; + let iter = SliceIter::new(input_str.as_bytes()); + let result = text_token!(&iter, "foo"); + assert!(result.is_complete()); + if let Result::Complete(i, o) = result { + assert_eq!(i.get_offset(), 3); + assert_eq!(o, "foo"); + } +} + +#[test] +fn test_text_token_fails() { + let input_str = "foo bar"; + let iter = SliceIter::new(input_str.as_bytes()); + let result = text_token!(&iter, "bar"); + assert!(result.is_fail()); +} + #[test] fn test_wrap_err_fail() { let input_str = "foo";