REFACTOR: Fix issue where text_token macro expected a reference.

This commit is contained in:
Jeremy Wall 2018-09-05 22:02:00 -05:00
parent 3f6bad4cd2
commit 9b3f69d7f4
2 changed files with 35 additions and 5 deletions

View File

@ -1,6 +1,7 @@
//! 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. /// Convenience macro for looking for a specific text token in a byte input stream.
#[macro_export]
macro_rules! text_token { macro_rules! text_token {
($i:expr, $e:expr) => {{ ($i:expr, $e:expr) => {{
use $crate::Error; use $crate::Error;
@ -19,19 +20,22 @@ macro_rules! text_token {
if count == $e.len() { if count == $e.len() {
Result::Complete(_i.clone(), $e) Result::Complete(_i.clone(), $e)
} else { } else {
Result::Fail(Error::new(format!("Expected {} but didn't get it.", $e), $i)) Result::Fail(Error::new(format!("Expected {} but didn't get it.", $e), &$i))
} }
}}; }};
} }
// FIXME(jwall): We need until!, not! and peek!. // 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 {
($i:expr, $f:ident) => { ($i:expr, $f:ident) => {
$f($i) $f($i)
}; };
($i:expr, $f:ident( $( $args:tt )* ) ) => {
$f($i, $($args)*)
};
} }
/// Turns Fails into Aborts. Allows you to turn any parse failure into a hard abort of the parser. /// Turns Fails into Aborts. Allows you to turn any parse failure into a hard abort of the parser.
@ -46,6 +50,10 @@ macro_rules! must {
} }
}; };
($i:expr, $f:ident( $( $args:tt )* ) ) => {
must!($i, run!($f($($args)*)))
};
($i:expr, $f:ident) => { ($i:expr, $f:ident) => {
must!($i, run!($f)) must!($i, run!($f))
}; };
@ -65,6 +73,10 @@ macro_rules! wrap_err {
} }
}}; }};
($i:expr, $f:ident( $( $args:tt )* ), $e:expr ) => {
wrap_err!($i, run!($f($($args)*)), $e:expr)
};
($i:expr, $f:ident, $e:expr) => { ($i:expr, $f:ident, $e:expr) => {
wrap_err!($i, run!($f), $e) wrap_err!($i, run!($f), $e)
}; };
@ -82,6 +94,10 @@ macro_rules! trap {
} }
}; };
($i:expr, $f:ident( $( $args:tt )* ) ) => {
trap!($i, run!($f($($args)*)))
};
($i:expr, $f:ident) => { ($i:expr, $f:ident) => {
trap!($i, run!($f)) trap!($i, run!($f))
}; };
@ -101,6 +117,10 @@ macro_rules! must_complete {
} }
}}; }};
($i:expr, $efn:expr, $f:ident( $( $args:tt )* ) ) => {
must_complete!($i, $efn, run!($f($($args)*)))
};
($i:expr, $efn:expr, $f:ident) => { ($i:expr, $efn:expr, $f:ident) => {
must_complete!($i, $efn, run!($f)) must_complete!($i, $efn, run!($f))
}; };
@ -153,6 +173,16 @@ macro_rules! do_each {
do_each!($i, _ => run!($f), $( $rest )* ) do_each!($i, _ => run!($f), $( $rest )* )
}; };
($i:expr, $val:ident => $f:ident( $(args:tt)* ), $($rest:tt)* ) => {
// If any single one of these matchers fails then all of them are failures.
do_each!($i, $val => run!($f($($args)*)), $( $rest )* )
};
($i:expr, _ => $f:ident( $(args:tt)* ), $($rest:tt)* ) => {
// If any single one of these matchers fails then all of them are failures.
do_each!($i, _ => run!($f($($args)*)), $( $rest )* )
};
// Our Terminal condition // Our Terminal condition
($i:expr, ( $($rest:tt)* ) ) => { ($i:expr, ( $($rest:tt)* ) ) => {
Result::Complete($i, ($($rest)*)) Result::Complete($i, ($($rest)*))

View File

@ -1,5 +1,5 @@
use super::iter::SliceIter;
use super::{Offsetable, Result}; use super::{Offsetable, Result};
use iter::SliceIter;
#[test] #[test]
fn test_slice_iter() { fn test_slice_iter() {
@ -70,7 +70,7 @@ fn parse_three(i: SliceIter<u8>) -> Result<SliceIter<u8>, String, String> {
fn test_text_token() { fn test_text_token() {
let input_str = "foo bar"; let input_str = "foo bar";
let iter = SliceIter::new(input_str.as_bytes()); let iter = SliceIter::new(input_str.as_bytes());
let result = text_token!(&iter, "foo"); let result = text_token!(iter, "foo");
assert!(result.is_complete()); assert!(result.is_complete());
if let Result::Complete(i, o) = result { if let Result::Complete(i, o) = result {
assert_eq!(i.get_offset(), 3); assert_eq!(i.get_offset(), 3);
@ -82,7 +82,7 @@ fn test_text_token() {
fn test_text_token_fails() { fn test_text_token_fails() {
let input_str = "foo bar"; let input_str = "foo bar";
let iter = SliceIter::new(input_str.as_bytes()); let iter = SliceIter::new(input_str.as_bytes());
let result = text_token!(&iter, "bar"); let result = text_token!(iter, "bar");
assert!(result.is_fail()); assert!(result.is_fail());
} }