diff --git a/src/lib.rs b/src/lib.rs index 8de4d8e..2a8cfdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,22 @@ where } } +fn pred(parser: P, pred_fn: F) -> impl Parser +where + P: Parser, + F: Fn(&O) -> bool, +{ + move |input| { + parser.parse(input).and_then(|(result, rest)| { + if pred_fn(&result) { + Ok((result, rest)) + } else { + Err(rest) + } + }) + } +} + fn zero_or_more(parser: P) -> impl Parser, I> where P: Parser, @@ -114,6 +130,13 @@ fn identifier(input: &str) -> ParseResult<&str, String, &str> { Ok((buf, &input[next_index..])) } +fn any_char(input: &str) -> ParseResult<&str, char, &str> { + match input.chars().next() { + Some(ch) => Ok((ch, &input[ch.len_utf8()..])), + None => Err(input), + } +} + #[cfg(test)] mod tests { use super::*; @@ -152,4 +175,10 @@ mod tests { let input = "bongo ecks"; assert_matches!(p.parse(input), Ok((v, "ecks")) if v.len() == 1); } + + #[test] + fn test_pred() { + let p = pred(any_char, |c| *c == 'f'); + assert_eq!(p.parse("frog"), Ok(('f', "rog"))); + } }