bogobble/partial/
charbool.rs1use super::PosTree;
2use crate::traits::*;
3
4pub struct S(pub &'static str);
5
6impl<'a> Parser<'a> for S {
7 type Out = &'static str;
8 fn parse(&self, it: &PIter<'a>) -> ParseRes<'a, Self::Out> {
9 let mut i2 = it.clone();
10 for c in self.0.chars() {
11 match i2.next() {
12 None => return Ok((i2, self.0, None)),
13 Some(nc) if nc == c => {}
14 _ => return Err(i2.err_s(self.0)),
15 }
16 }
17 Ok((i2, self.0, None))
18 }
19}
20
21pub trait PartCharBool: CharBool + Sized {
22 fn p_until<'a, P: Parser<'a, Out = PosTree<I>>, I: Clone>(
23 self,
24 p: P,
25 i: I,
26 ) -> PCUntil<Self, P, I> {
27 PCUntil { c: self, p, i }
28 }
29}
30
31impl<C: CharBool> PartCharBool for C {}
32
33pub struct PCUntil<C, P, I> {
34 c: C,
35 p: P,
36 i: I,
37}
38
39impl<'a, C: CharBool, P: Parser<'a, Out = PosTree<I>>, I: Clone> Parser<'a> for PCUntil<C, P, I> {
40 type Out = (PosTree<I>, P::Out);
41 fn parse(&self, it: &PIter<'a>) -> ParseRes<'a, Self::Out> {
42 let mut i2 = it.clone();
43 loop {
44 let p_err = match self.p.parse(&i2) {
45 Ok((i3, r2, e_op)) => {
46 let fin = i3.index();
47 return Ok((
48 i3,
49 (PosTree::new(it.index(), fin, self.i.clone()), r2),
50 e_op,
51 ));
52 }
53 Err(e) => e,
54 };
55 match i2.next() {
56 Some(c) if self.c.char_bool(c) => {}
57 Some(_) => return Err(i2.err(self.c.expected())),
58 None => return Err(p_err),
59 }
60 }
61 }
62}