use crate::{InputToken, Parser};
pub fn either<P1, P2, IT, O>(parser1: &P1, parser2: &P2) -> impl Parser<IT, O>
where
P1: Parser<IT, O>,
P2: Parser<IT, O>,
IT: InputToken,
{
|input| {
let initial_length = input.consumed_count();
match parser1(input) {
Ok(token) => Ok(token),
Err(_) if input.consumed_count() == initial_length => parser2(input),
Err(e) => Err(e),
}
}
}
#[cfg(test)]
mod tests {
use crate::input::Position;
use crate::*;
#[test]
fn success_first() {
let parser1 = is('h');
let parser2 = is('j');
let mut input = Input::new_from_chars("h".chars(), None);
let parse_either = either(&parser1, &parser2);
let output = parse_either(&mut input).unwrap();
assert_eq!(output, 'h');
assert!(end_of_input()(&mut input).is_ok()); }
#[test]
fn success_second() {
let parser1 = is('h');
let parser2 = is('j');
let mut input = Input::new_from_chars("j".chars(), None);
let parse_either = either(&parser1, &parser2);
let output = parse_either(&mut input).unwrap();
assert_eq!(output, 'j');
assert!(end_of_input()(&mut input).is_ok()); }
#[test]
fn fail_not_consuming() {
let parser1 = is('h');
let parser2 = is('j');
let mut input = Input::new_from_chars("kello".chars(), None);
let parse_either = either(&parser1, &parser2);
let mismatch = Mismatch::new('j', 'k');
assert_eq!(
parse_either(&mut input),
Err(Error::UnexpectedToken(
None,
Position::new(1, 1),
Some(mismatch)
))
);
assert_eq!(any()(&mut input), Ok('k')); }
#[test]
fn fail_consuming() {
let parser1 = is('h');
let parser2 = is('j');
let mut input = Input::new_from_chars("hello".chars(), None);
let consuming_parser = |input: &mut Input<_>| {
parser1(input)?;
parser2(input)
};
let parse_either = either(&consuming_parser, &parser2);
let output = parse_either(&mut input);
let mismatch = Mismatch::new('j', 'e');
assert_eq!(
output,
Err(Error::UnexpectedToken(
None,
Position::new(1, 2),
Some(mismatch)
))
);
assert_eq!(any()(&mut input), Ok('e')); }
}