Skip to main content

oni_comb_parser/combinator/
many.rs

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