Skip to main content

gobble/
skip.rs

1use crate::chars::*;
2use crate::iter::LCChars;
3use crate::ptrait::{ParseRes, Parser};
4
5pub fn do_skip_c<'a, CB: CharBool>(
6    it: &LCChars<'a>,
7    cb: &CB,
8    min: usize,
9    exact: bool,
10) -> ParseRes<'a, ()> {
11    let mut it = it.clone();
12    let mut done = 0;
13    loop {
14        let it2 = it.clone();
15        match it.next() {
16            Some(c) if cb.char_bool(c) => done += 1,
17            Some(_) | None => {
18                if done >= min {
19                    let eo = it2.err_oc(cb);
20                    return Ok((it2, (), eo));
21                } else {
22                    return it2.err_r(cb.expected());
23                }
24            }
25        }
26        if done == min && exact {
27            return Ok((it, (), None));
28        }
29    }
30}
31
32pub fn do_skip_p<'a, P: Parser>(
33    it: &LCChars<'a>,
34    p: &P,
35    min: usize,
36    exact: bool,
37) -> ParseRes<'a, ()> {
38    let mut it = it.clone();
39    let mut done = 0;
40    loop {
41        let it2 = it.clone();
42        it = match p.parse(&it) {
43            Ok((nit, _, _)) => {
44                done += 1;
45                nit
46            }
47            Err(e) => {
48                if done >= min {
49                    return Ok((it2, (), Some(e)));
50                } else {
51                    return Err(e);
52                }
53            }
54        };
55        if done == min && exact {
56            return Ok((it, (), None));
57        }
58    }
59}
60
61pub struct CharSkip<CB: CharBool> {
62    pub cb: CB,
63}
64
65impl<CB: CharBool> Parser for CharSkip<CB> {
66    type Out = ();
67    fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, ()> {
68        do_skip_c(it, &self.cb, 0, false)
69    }
70}
71
72#[derive(Clone)]
73pub struct CharSkipPlus<CB: CharBool> {
74    pub cb: CB,
75}
76
77impl<CB: CharBool> Parser for CharSkipPlus<CB> {
78    type Out = ();
79    fn parse<'a>(&self, i: &LCChars<'a>) -> ParseRes<'a, ()> {
80        do_skip_c(i, &self.cb, 1, false)
81    }
82}
83#[derive(Clone)]
84pub struct CharSkipExact<CB: CharBool> {
85    pub cb: CB,
86    pub n: usize,
87}
88
89impl<CB: CharBool> Parser for CharSkipExact<CB> {
90    type Out = ();
91    fn parse<'a>(&self, i: &LCChars<'a>) -> ParseRes<'a, ()> {
92        do_skip_c(i, &self.cb, self.n, true)
93    }
94}
95
96pub fn ig_star<A: Parser>(a: A) -> PSkipStar<A> {
97    PSkipStar { a }
98}
99pub fn ig_plus<A: Parser>(a: A) -> PSkipPlus<A> {
100    PSkipPlus { a }
101}
102pub fn ig_exact<A: Parser>(a: A, n: usize) -> PSkipExact<A> {
103    PSkipExact { a, n }
104}
105
106#[derive(Clone)]
107pub struct PSkipStar<A: Parser> {
108    pub a: A,
109}
110impl<A: Parser> Parser for PSkipStar<A> {
111    type Out = ();
112    fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, ()> {
113        do_skip_p(it, &self.a, 0, false)
114    }
115}
116
117#[derive(Clone)]
118pub struct PSkipPlus<A: Parser> {
119    pub a: A,
120}
121impl<A: Parser> Parser for PSkipPlus<A> {
122    type Out = ();
123    fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, ()> {
124        do_skip_p(it, &self.a, 1, false)
125    }
126}
127
128#[derive(Clone)]
129pub struct PSkipExact<A: Parser> {
130    pub a: A,
131    pub n: usize,
132}
133impl<A: Parser> Parser for PSkipExact<A> {
134    type Out = ();
135    fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, ()> {
136        do_skip_p(it, &self.a, self.n, true)
137    }
138}
139
140pub fn skip_2_star<A: Parser, B: Parser>(a: A, b: B) -> Skip2Star<A, B> {
141    Skip2Star { a, b }
142}
143
144pub struct Skip2Star<A: Parser, B: Parser> {
145    a: A,
146    b: B,
147}
148
149impl<A: Parser, B: Parser> Parser for Skip2Star<A, B> {
150    type Out = ();
151    fn parse<'a>(&self, it: &LCChars<'a>) -> ParseRes<'a, ()> {
152        let mut it = it.clone();
153        loop {
154            if let Ok((nit, _, _)) = self.a.parse(&it) {
155                it = nit;
156            } else if let Ok((nit, _, _)) = self.b.parse(&it) {
157                it = nit;
158            } else {
159                return Ok((it, (), None));
160            }
161        }
162    }
163}