Skip to main content

oni_comb_parser/combinator/
sep_by.rs

1use alloc::vec;
2use alloc::vec::Vec;
3
4use crate::fail::{Fail, PResult};
5use crate::input::Input;
6use crate::parser::Parser;
7
8pub struct SepBy0<P, S> {
9  pub(crate) parser: P,
10  pub(crate) sep: S,
11}
12
13impl<I, P, S> Parser<I> for SepBy0<P, S>
14where
15  I: Input,
16  P: Parser<I>,
17  S: Parser<I, Error = P::Error>,
18{
19  type Error = P::Error;
20  type Output = Vec<P::Output>;
21
22  #[inline]
23  fn parse_next(&mut self, input: &mut I) -> PResult<Self::Output, Self::Error> {
24    let mut items = Vec::new();
25
26    // 最初の要素
27    let cp = input.checkpoint();
28    match self.parser.parse_next(input) {
29      Ok(v) => items.push(v),
30      Err(Fail::Backtrack(_)) => {
31        input.reset(cp);
32        return Ok(items);
33      }
34      Err(e) => return Err(e),
35    }
36
37    // sep + 要素 の繰り返し
38    loop {
39      let cp = input.checkpoint();
40      match self.sep.parse_next(input) {
41        Ok(_) => {}
42        Err(Fail::Backtrack(_)) => {
43          input.reset(cp);
44          break;
45        }
46        Err(e) => return Err(e),
47      }
48      match self.parser.parse_next(input) {
49        Ok(v) => items.push(v),
50        Err(Fail::Backtrack(_)) => {
51          input.reset(cp);
52          break;
53        }
54        Err(e) => return Err(e),
55      }
56    }
57
58    Ok(items)
59  }
60}
61
62pub struct SepBy1<P, S> {
63  pub(crate) parser: P,
64  pub(crate) sep: S,
65}
66
67impl<I, P, S> Parser<I> for SepBy1<P, S>
68where
69  I: Input,
70  P: Parser<I>,
71  S: Parser<I, Error = P::Error>,
72{
73  type Error = P::Error;
74  type Output = Vec<P::Output>;
75
76  #[inline]
77  fn parse_next(&mut self, input: &mut I) -> PResult<Self::Output, Self::Error> {
78    // 最初の要素は必須
79    let first = self.parser.parse_next(input)?;
80    let mut items = vec![first];
81
82    // sep + 要素 の繰り返し
83    loop {
84      let cp = input.checkpoint();
85      match self.sep.parse_next(input) {
86        Ok(_) => {}
87        Err(Fail::Backtrack(_)) => {
88          input.reset(cp);
89          break;
90        }
91        Err(e) => return Err(e),
92      }
93      match self.parser.parse_next(input) {
94        Ok(v) => items.push(v),
95        Err(Fail::Backtrack(_)) => {
96          input.reset(cp);
97          break;
98        }
99        Err(e) => return Err(e),
100      }
101    }
102
103    Ok(items)
104  }
105}