FEATURE: a text token convenience macro.

This commit is contained in:
Jeremy Wall 2018-09-05 20:43:43 -05:00
parent fe1b0fd154
commit 3f6bad4cd2
2 changed files with 48 additions and 0 deletions

View File

@ -1,5 +1,31 @@
//! Contains the helper macros for abortable-parser. //! 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. /// Converts a function indentifier into a macro call. Useful when writing your own macro combinator.
#[macro_export] #[macro_export]
macro_rules! run { 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_export]
macro_rules! wrap_err { macro_rules! wrap_err {
($i:expr, $f:ident!( $( $args:tt )* ), $e:expr) => {{ ($i:expr, $f:ident!( $( $args:tt )* ), $e:expr) => {{

View File

@ -66,6 +66,26 @@ fn parse_three(i: SliceIter<u8>) -> Result<SliceIter<u8>, 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] #[test]
fn test_wrap_err_fail() { fn test_wrap_err_fail() {
let input_str = "foo"; let input_str = "foo";