1use std::{
2 convert::Infallible,
3 error::Error,
4 fmt::Display,
5 marker::PhantomData,
6 ops::{Range, RangeBounds},
7};
8
9use crate::{sequence::Sequence, Parser, ParserError, ParserType};
10#[derive(Clone, Debug, Copy)]
19pub struct TryReducerError;
20impl Display for TryReducerError {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 f.write_str("TryReducerFailed")
23 }
24}
25
26impl Error for TryReducerError {}
27
28pub trait TryReducer<'a, Acc, T, FType, FErr, Out, I: ?Sized> {
44 fn try_reduce(&self, acc: &mut Acc, val: T) -> Result<(), FErr>;
45 fn finalize(&self, acc: Acc, orig_input: &'a I, new_input: &'a I) -> Out;
46}
47
48pub struct ResultReducer;
49impl<'a, Acc, T, F, FErr, I: ?Sized> TryReducer<'a, Acc, T, ResultReducer, FErr, Acc, I> for F
50where
51 F: Fn(&mut Acc, T) -> Result<(), FErr>,
52{
53 fn try_reduce(&self, acc: &mut Acc, val: T) -> Result<(), FErr> {
54 self(acc, val)
55 }
56 fn finalize(&self, acc: Acc, _orig_input: &'a I, _new_input: &'a I) -> Acc {
57 acc
58 }
59}
60pub struct OptionReducer();
61impl<'a, Acc, T, F, I: ?Sized> TryReducer<'a, Acc, T, OptionReducer, TryReducerError, Acc, I> for F
62where
63 F: Fn(&mut Acc, T) -> Option<()>,
64{
65 fn try_reduce(&self, acc: &mut Acc, val: T) -> Result<(), TryReducerError> {
66 self(acc, val).ok_or(TryReducerError).map(|_| ())
67 }
68 fn finalize(&self, acc: Acc, _orig_input: &'a I, _new_input: &'a I) -> Acc {
69 acc
70 }
71}
72pub struct BoolReducer;
73impl<'a, Acc, T, F, I: ?Sized> TryReducer<'a, Acc, T, BoolReducer, TryReducerError, Acc, I> for F
74where
75 F: Fn(&mut Acc, T) -> bool,
76{
77 fn try_reduce(&self, acc: &mut Acc, val: T) -> Result<(), TryReducerError> {
78 if self(acc, val) {
79 Ok(())
80 } else {
81 Err(TryReducerError)
82 }
83 }
84 fn finalize(&self, acc: Acc, _orig_input: &'a I, _new_input: &'a I) -> Acc {
85 acc
86 }
87}
88
89pub struct InfallibleReducer;
90impl<'a, Acc, T, F, I: ?Sized> TryReducer<'a, Acc, T, InfallibleReducer, Infallible, Acc, I> for F
91where
92 F: Fn(&mut Acc, T) -> (),
93{
94 fn try_reduce(&self, acc: &mut Acc, val: T) -> Result<(), Infallible> {
95 Ok(self(acc, val)).map(|_| ())
96 }
97 fn finalize(&self, acc: Acc, _orig_input: &'a I, _new_input: &'a I) -> Acc {
98 acc
99 }
100}
101
102pub struct InputSliceReducer;
103impl<'a, T, I: ?Sized> TryReducer<'a, (), T, InputSliceReducer, Infallible, &'a I, I>
104 for InputSliceReducer
105where
106 I: Sequence,
107{
108 fn try_reduce(&self, _acc: &mut (), _val: T) -> Result<(), Infallible> {
109 Ok(())
110 }
111 fn finalize(&self, _acc: (), orig_input: &'a I, new_input: &'a I) -> &'a I {
112 orig_input.subtract(new_input)
113 }
114}
115
116pub struct Reducer<Reduce, Acc: Clone> {
117 pub acc: Acc,
118 pub reduce_operator: Reduce,
119}
120pub struct Repeat<P, ParI: ?Sized, ParO, ParE, F, Acc: Clone> {
126 parser: P,
127 reducer: Reducer<F, Acc>,
128 bounds: Range<usize>,
129 phantom_i: PhantomData<ParI>,
130 phantom_o: PhantomData<ParO>,
131 phantom_e: PhantomData<ParE>,
132}
133
134impl<P, ParI: ?Sized, ParO, ParE, F, Acc: Clone> Repeat<P, ParI, ParO, ParE, F, Acc> {
135 pub fn new(parser: P, reducer: Reducer<F, Acc>, bounds: Range<usize>) -> Self {
139 Repeat {
140 parser,
141 reducer,
142 bounds,
143 phantom_i: PhantomData,
144 phantom_o: PhantomData,
145 phantom_e: PhantomData,
146 }
147 }
148}
149
150pub struct RepeatParser<PType, ReducerOut, FErr> {
151 ptype: PhantomData<PType>,
152 reducer_out: PhantomData<ReducerOut>,
153 ferr: PhantomData<FErr>,
154}
155
156fn loc<I: ?Sized>(seq: &I) -> usize {
157 seq as *const I as *const u8 as usize
158}
159
160impl<'a, P, I, O, E, PType, F, Acc, FErr, ReducerOut, AccOut>
167 Parser<'a, I, AccOut, E, RepeatParser<PType, ReducerOut, FErr>> for Repeat<P, I, O, E, F, Acc>
168where
169 E: ParserError,
170 I: ?Sized + Sequence,
171 P: Parser<'a, I, O, E, PType>,
172 Acc: Clone,
173 FErr: 'static + Send + Sync + Error,
174 F: TryReducer<'a, Acc, O, ReducerOut, FErr, AccOut, I>,
175{
176 fn fab(&self, input: &mut &'a I) -> Result<AccOut, E> {
177 let mut res = self.reducer.acc.clone();
178 let mut repetitions: usize = 0;
179 let mut last_location = *input;
180 let orig_input = *input;
181 if self.bounds.is_empty() {
182 return Err(E::from_parser_error(*input, ParserType::Repeat));
183 }
184 loop {
185 if repetitions == self.bounds.end - 1 {
187 return Ok(self
188 .reducer
189 .reduce_operator
190 .finalize(res, orig_input, input));
191 }
192 let loc_before_iteration = *input;
195 match self.parser.fab(input) {
196 Ok(val) => {
198 if loc(*input) == loc(last_location) {
200 let mut err =
201 E::from_parser_error(loc_before_iteration, ParserType::RepeatIter);
202 *input = orig_input;
203 err.add_context(orig_input, ParserType::Repeat);
204 return Err(err);
205 }
206 last_location = *input;
207 if let Err(err) = self.reducer.reduce_operator.try_reduce(&mut res, val) {
210 let mut err = E::from_external_error(
211 loc_before_iteration,
212 ParserType::RepeatIter,
213 err,
214 );
215 *input = orig_input;
216 err.add_context(orig_input, ParserType::Repeat);
219 return Err(err);
220 }
221 }
222 Err(_) => {
223 if self.bounds.contains(&repetitions) {
225 return Ok(self
226 .reducer
227 .reduce_operator
228 .finalize(res, orig_input, input));
229 } else {
230 *input = orig_input;
231 return Err(E::from_parser_error(*input, ParserType::Repeat));
232 }
233 }
234 }
235 repetitions += 1;
236 }
237 }
238}
239
240impl<P, ParI: ?Sized, ParO, ParE, F, Acc: Clone> Repeat<P, ParI, ParO, ParE, F, Acc> {
241 pub fn min(self, min: usize) -> Self {
245 Repeat::new(self.parser, self.reducer, min..self.bounds.end)
246 }
247 pub fn max(self, max: usize) -> Self {
252 Repeat::new(self.parser, self.reducer, self.bounds.start..max)
253 }
254 pub fn bound<B: RangeBounds<usize>>(self, bounds: B) -> Self {
258 let lower = match bounds.start_bound() {
259 std::ops::Bound::Included(val) => *val,
260 std::ops::Bound::Excluded(val) => {
262 if *val == usize::MAX {
263 panic!("The lower bound for the range shouldn't be usize::MAX")
264 } else {
265 *val + 1
266 }
267 }
268 std::ops::Bound::Unbounded => 0,
269 };
270 let upper = match bounds.end_bound() {
271 std::ops::Bound::Included(val) => {
273 if *val == usize::MAX {
274 *val
275 } else {
276 *val + 1
277 }
278 }
279 std::ops::Bound::Excluded(val) => *val,
280 std::ops::Bound::Unbounded => usize::MAX,
281 };
282 Repeat::new(self.parser, self.reducer, lower..upper)
283 }
284 pub fn as_input_slice(self) -> Repeat<P, ParI, ParO, ParE, InputSliceReducer, ()> {
288 Repeat::new(
289 self.parser,
290 Reducer {
291 acc: (),
292 reduce_operator: InputSliceReducer,
293 },
294 self.bounds,
295 )
296 }
297 pub fn reduce<NewAcc: Clone, NewF>(
307 self,
308 acc: NewAcc,
309 reduce_fn: NewF,
310 ) -> Repeat<P, ParI, ParO, ParE, NewF, NewAcc> {
311 Repeat::new(
312 self.parser,
313 Reducer {
314 acc,
315 reduce_operator: reduce_fn,
316 },
317 self.bounds,
318 )
319 }
320}