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}