Skip to main content

oni_comb_parser/combinator/
many1_fold.rs

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