Predicate

This commit is contained in:
Greg Shuflin 2022-10-16 00:39:41 -07:00
parent 870c9beb54
commit 0c6c59da07

View File

@ -59,6 +59,22 @@ where
} }
} }
fn pred<P, F, I, O>(parser: P, pred_fn: F) -> impl Parser<I, O, I>
where
P: Parser<I, O, I>,
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<P, I, O>(parser: P) -> impl Parser<I, Vec<O>, I> fn zero_or_more<P, I, O>(parser: P) -> impl Parser<I, Vec<O>, I>
where where
P: Parser<I, O, I>, P: Parser<I, O, I>,
@ -114,6 +130,13 @@ fn identifier(input: &str) -> ParseResult<&str, String, &str> {
Ok((buf, &input[next_index..])) 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -152,4 +175,10 @@ mod tests {
let input = "bongo ecks"; let input = "bongo ecks";
assert_matches!(p.parse(input), Ok((v, "ecks")) if v.len() == 1); 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")));
}
} }