Skip to main content

oni_comb_parser/combinator/
chainl1.rs

1use crate::fail::{Fail, PResult};
2use crate::input::Input;
3use crate::parser::Parser;
4
5pub struct ChainL1<P, Op> {
6  pub(crate) operand: P,
7  pub(crate) operator: Op,
8}
9
10impl<I, P, Op, F> Parser<I> for ChainL1<P, Op>
11where
12  I: Input,
13  P: Parser<I>,
14  Op: Parser<I, Output = F, Error = P::Error>,
15  F: FnMut(P::Output, P::Output) -> P::Output,
16{
17  type Error = P::Error;
18  type Output = P::Output;
19
20  #[inline]
21  fn parse_next(&mut self, input: &mut I) -> PResult<Self::Output, Self::Error> {
22    let mut acc = self.operand.parse_next(input)?;
23    loop {
24      let cp = input.checkpoint();
25      match self.operator.parse_next(input) {
26        Ok(mut f) => match self.operand.parse_next(input) {
27          Ok(rhs) => acc = f(acc, rhs),
28          Err(Fail::Backtrack(_)) => {
29            input.reset(cp);
30            break;
31          }
32          Err(e) => return Err(e),
33        },
34        Err(Fail::Backtrack(_)) => {
35          input.reset(cp);
36          break;
37        }
38        Err(e) => return Err(e),
39      }
40    }
41    Ok(acc)
42  }
43}