Skip to main content

oni_comb_parser/combinator/
or.rs

1use crate::error::MergeError;
2use crate::fail::{Fail, PResult};
3use crate::input::Input;
4use crate::parser::Parser;
5
6pub struct Or<P1, P2> {
7  pub(crate) left: P1,
8  pub(crate) right: P2,
9}
10
11impl<I, P1, P2> Parser<I> for Or<P1, P2>
12where
13  I: Input,
14  P1: Parser<I>,
15  P1::Error: MergeError,
16  P2: Parser<I, Output = P1::Output, Error = P1::Error>,
17{
18  type Error = P1::Error;
19  type Output = P1::Output;
20
21  #[inline]
22  fn parse_next(&mut self, input: &mut I) -> PResult<Self::Output, Self::Error> {
23    let cp = input.checkpoint();
24    match self.left.parse_next(input) {
25      Ok(v) => Ok(v),
26      Err(Fail::Backtrack(left_err)) => {
27        input.reset(cp);
28        match self.right.parse_next(input) {
29          ok @ Ok(_) => ok,
30          Err(Fail::Backtrack(right_err)) => Err(Fail::Backtrack(left_err.merge(right_err))),
31          err => err,
32        }
33      }
34      Err(Fail::Cut(e)) => Err(Fail::Cut(e)),
35      Err(Fail::Incomplete) => Err(Fail::Incomplete),
36      Err(Fail::ZeroProgress) => Err(Fail::ZeroProgress),
37    }
38  }
39}