choice combinator

This commit is contained in:
Greg Shuflin 2022-10-16 01:29:48 -07:00
parent 00d866f2a1
commit 8002b83a86

View File

@ -19,6 +19,17 @@ trait Parser<I, O, E> {
BoxedParser::new(map(self, map_fn)) BoxedParser::new(map(self, map_fn))
} }
fn to<'a, O2>(self, item: O2) -> BoxedParser<'a, I, O2, E>
where
Self: Sized + 'a,
I: 'a,
O: 'a,
O2: Clone + 'a,
E: 'a,
{
self.map(move |_| item.clone())
}
fn then<'a, P, O2>(self, next_parser: P) -> BoxedParser<'a, I, (O, O2), E> fn then<'a, P, O2>(self, next_parser: P) -> BoxedParser<'a, I, (O, O2), E>
where where
Self: Sized + 'a, Self: Sized + 'a,
@ -182,6 +193,18 @@ fn any_char(input: &str) -> ParseResult<&str, char, &str> {
} }
} }
fn choice<P1, P2, I, O, E>(parser1: P1, parser2: P2) -> impl Parser<I, O, E>
where
P1: Parser<I, O, E>,
P2: Parser<I, O, E>,
I: Copy,
{
move |input| match parser1.parse(input) {
ok @ Ok(..) => ok,
Err(_e) => parser2.parse(input),
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -229,4 +252,10 @@ mod tests {
let p = pred(any_char, |c| *c == 'f'); let p = pred(any_char, |c| *c == 'f');
assert_eq!(p.parse("frog"), Ok(('f', "rog"))); assert_eq!(p.parse("frog"), Ok(('f', "rog")));
} }
#[test]
fn test_choice() {
let p = choice(literal("gnostika").to(1), one_or_more(literal(" ")).to(2));
assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine")));
}
} }