1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
use std::{collections::{HashMap, BTreeMap}, hash::Hash};

use crate::{slicelike::SliceLike, core::{Parser, AnpaState}, parsers::success};

/// Create a new parser by taking the result of `p`, and applying `f`.
///
/// ### Arguments
/// * `p` - the parser
/// * `f` - the function to generate the new parser
#[inline]
pub fn bind<I, O1, O2, P, S>(p: impl Parser<I, O1, S>,
                             f: impl FnOnce(O1) -> P + Copy
) -> impl Parser<I, O2, S> where P: Parser<I, O2, S> {
    create_parser!(s, f(p(s)?)(s))
}

/// Create a new parser by applying a transformation `f` to the result of `p`.
/// This differs from `bind` in that the transformation does not return a new
/// parser. Use this combinator if you just want to modify the result.
///
/// ### Arguments
/// * `p` - the parser
/// * `f` - the transformation function.
#[inline]
pub fn map<I, O, O2, S>(p: impl Parser<I, O, S>,
                        f: impl FnOnce(O) -> O2 + Copy
) -> impl Parser<I, O2, S> {
    lift!(f, p)
}

/// Transform the parser `p` into a parser with a different result by means of `Into`.
/// The existing type must implement `Into<T>` for the requested type `T`.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn into_type<I, O: Into<T>, T, S>(p: impl Parser<I, O, S>) -> impl Parser<I, T, S> {
    map(p, O::into)
}

/// Accept or reject the parse based on the predicate `f`.
///
/// ### Arguments
/// * `p` - the parser
/// * `f` - the predicate
#[inline]
pub fn filter<I, O, S>(p: impl Parser<I, O, S>,
                       f: impl FnOnce(&O) -> bool + Copy
) -> impl Parser<I, O, S> {
    create_parser!(s, p(s).filter(f))
}

/// Create a new parser by applying a transformation `f` to the result of `p`.
/// Unlike `map`, this combinator allows optional rejection of the parse by returning
/// `Some` or `None` in the transformation.
///
/// ### Arguments
/// * `p` - the parser
/// * `f` - the transformation function.
#[inline]
pub fn map_if<I, O, O2, S>(p: impl Parser<I, O, S>,
                           f: impl FnOnce(O) -> Option<O2> + Copy
) -> impl Parser<I, O2, S> {
    create_parser!(s, {
        p(s).and_then(f)
    })
}

/// Transform a parser to a parser that always succeeds. The resulting parser will
/// have its result type changed to `Option`, to allow for introspection of the result
/// of the parse.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn succeed<I, O, S>(p: impl Parser<I, O, S>) -> impl Parser<I, Option<O>, S> {
    create_parser!(s, {
        Some(p(s))
    })
}

/// Transform a parser to a parser that does not consume any input.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn peek<I: Copy, O, S>(p: impl Parser<I, O, S>) -> impl Parser<I, O, S> {
    create_parser!(s, {
        let pos = s.input;
        let res = p(s);
        s.input = pos;
        res
    })
}

/// Transform a parser to a parser that only succeeds if the parsed sequence is not empty.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn not_empty<I, O: SliceLike, S>(p: impl Parser<I, O, S>) -> impl Parser<I, O, S> {
    filter(p, |r| !r.slice_is_empty())
}

/// Transform a parser to a parser that does not consume any input on failure.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn attempt<I: Copy, O, S>(p: impl Parser<I, O, S>) -> impl Parser<I, O, S> {
    create_parser!(s, {
        let pos = s.input;
        let res = p(s);
        if res.is_none() {
            s.input = pos;
        }
        res
    })
}

/// Transform a parser to a parser that along with its result also returns how many items that
/// were parsed.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn count_consumed<I: SliceLike, O, S>(p: impl Parser<I, O, S>) -> impl Parser<I, (usize, O), S> {
    create_parser!(s, {
        let old = s.input.slice_len();
        let res = p(s)?;
        let count = old - s.input.slice_len();
        Some((count, res))
    })
}

/// Transform a parser to a parser that along with its result also returns the input that
/// was parsed.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn and_parsed<I: SliceLike, O, S>(p: impl Parser<I, O, S>) -> impl Parser<I, (I, O), S> {
    create_parser!(s, {
        let old_input = s.input;
        let res = p(s)?;
        Some((old_input.slice_to(old_input.slice_len() - s.input.slice_len()), res))
    })
}

/// Transform a parser to a parser that ignores its result and instead returns the input that
/// was parsed to produce the result.
///
/// ### Arguments
/// * `p` - the parser
#[inline]
pub fn get_parsed<I: SliceLike, O, S>(p: impl Parser<I, O, S>) -> impl Parser<I, I, S> {
    create_parser!(s, {
        let old_input = s.input;
        p(s)?;
        Some(old_input.slice_to(old_input.slice_len() - s.input.slice_len()))
    })
}

/// Transform a parser to a parser that only succeeds if it can be applied `times` times without
/// failure.
///
/// ### Arguments
/// * `times` - the number of times to apply `p`
/// * `p` - the parser
#[inline]
pub fn times<I: SliceLike, O, S>(times: u32, p: impl Parser<I, O, S>) -> impl Parser<I, I, S> {
    create_parser!(s, {
        let old_input = s.input;
        for _ in 0..times {
            p(s)?;
        }
        Some(old_input.slice_to(old_input.slice_len() - s.input.slice_len()))
    })
}

/// Combine one parser with another, while ignoring the result of the former.
/// The second parser will only be attempted if the first succeeds.
///
/// ### Arguments
/// * `p1` - the first parser (result will be ignored)
/// * `p2` - the second parser
#[inline]
pub fn right<I, S, O1, O2>(p1: impl Parser<I, O1, S>,
                           p2: impl Parser<I, O2, S>
) ->  impl Parser<I, O2, S> {
    create_parser!(s, {
        p1(s).and_then(|_| p2(s))
    })
}

/// Combine one parser with another, while ignoring the result of the latter.
/// The second parser will only be attempted if the first succeeds.
///
/// ### Arguments
/// * `p1` - the first parser
/// * `p2` - the second parser (result will be ignored)
#[inline]
pub fn left<I, S, O1, O2>(p1: impl Parser<I, O1, S>,
                          p2: impl Parser<I, O2, S>
) ->  impl Parser<I, O1, S> {
    create_parser!(s, {
        p1(s).and_then(|res| p2(s).map(|_| res))
    })
}

/// Combine three parsers, returning the result of the middle one.
///
/// ### Arguments
/// * `p1` - the first parser (result will be ignored)
/// * `p2` - the second parser
/// * `p3` - the third parser (result will be ignored)
#[inline]
pub fn middle<I, S, O1, O2, O3>(p1: impl Parser<I, O1, S>,
                                p2: impl Parser<I, O2, S>,
                                p3: impl Parser<I, O3, S>
) ->  impl Parser<I, O2, S> {
    right(p1, left(p2, p3))
}

macro_rules! internal_or {
    ($id:ident, $allow_partial:tt, $comment:tt) => {
        /// Create a parser that first tries the one parser `p1`, and if it fails, tries the second parser
        /// `p2`.
        /// Both parsers must have the same result type.
        ///
        /// $comment
        ///
        /// ### Arguments
        /// * `p1` - the first parser
        /// * `p2` - the second parser
        #[inline]
        pub fn $id<I: SliceLike, O, S>(p1: impl Parser<I, O, S>,
                                       p2: impl Parser<I, O, S>
        ) -> impl Parser<I, O, S> {
            create_parser!(s, {
                let pos = s.input;
                p1(s).or_else(|| {
                    if !$allow_partial && s.input.slice_len() != pos.slice_len() {
                        None
                    } else {
                        s.input = pos;
                        p2(s)
                    }
                })
            })
        }
    }
}

internal_or!(or, true, "");
internal_or!(or_no_partial, false, "This differs from `or` in that it will not attempt to use `p2` in case there was any consumed input while processing `p1`.");

macro_rules! internal_or_diff {
    ($id:ident, $allow_partial:tt, $comment:tt) => {
        /// Create a parser that first tries the one parser `p1`, and if it fails, tries the second parser
        /// `p2`.
        /// This version of `or` can accept parsers with different result types, and will therefore have
        /// a result type of `()`.
        ///
        /// $comment
        ///
        /// ### Arguments
        /// * `p1` - the first parser
        /// * `p2` - the second parser
        #[inline]
        pub fn $id<I: SliceLike, O1, O2, S>(p1: impl Parser<I, O1, S>,
                                            p2: impl Parser<I, O2, S>
        ) -> impl Parser<I, (), S> {
            create_parser!(s, {
                let pos = s.input;
                if p1(s).is_some() {
                    Some(())
                } else {
                    if (!$allow_partial && s.input.slice_len() != pos.slice_len()) {
                        None
                    } else {
                        s.input = pos;
                        p2(s).map(|_| ())
                    }
                }
            })
        }
    }
}

internal_or_diff!(or_diff, true, "");
internal_or_diff!(or_diff_no_partial, false, "This differs from `or_diff` in that it will not attempt to use `p2` in case there was any consumed input while processing `p1`.");

/// Create a parser that allows for using and modifying the user state while transforming
/// the result.
///
/// ### Arguments
/// * `f` - a transformation function that is also allowed to use and modify the user state.
/// * `p` - the parser
#[inline]
pub fn lift_to_state<I, S, O1, O2>(f: impl FnOnce(&mut S, O1) -> O2 + Copy,
                                   p: impl Parser<I, O1, S>
) -> impl Parser<I, O2, S> {
    create_parser!(s, {
        p(s).map(|res| f(&mut s.user_state, res))
    })
}

/// Only for use with the `many` family of combinators. Use this function to create the separator
/// argument when parsing multiple elements.
///
/// ### Arguments
/// * `p` - a parser for the separator
/// * `allow_trailing` - whether a trailing separator is allowed.
#[inline]
pub fn separator<I, O, S>(p: impl Parser<I, O, S>, allow_trailing: bool) -> Option<(bool, impl Parser<I, O, S>)> {
    Some((allow_trailing, p))
}

/// Only for use with the `many` family of combinators. Use this function to create the separator
/// argument when no separator should be present.
#[inline]
pub fn no_separator<I, S>() -> Option<(bool, impl Parser<I, (), S>)> {
    if true {
        None
    } else {
        // Only for type checking
        Some((false, success()))
    }
}

#[inline(always)]
fn many_internal<I, O, O2, S>(
    s: &mut AnpaState<I, S>,
    p: impl Parser<I, O, S>,
    mut f: impl FnMut(O) -> (),
    allow_empty: bool,
    separator: Option<(bool, impl Parser<I, O2, S>)>
) -> Option<()> {
    let mut successes = false;
    loop {
        let Some(res) = p(s) else {
            if let (Some((false, _)), true) = (separator, successes) {
                return None
            }
            break;
        };

        f(res);
        successes = true;

        if let Some((_, sep)) = separator {
            if sep(s).is_none() {
                break;
            }
        }
    }
    (allow_empty || successes).then_some(())
}

/// Apply a parser until it fails and return the parsed input.
///
/// ### Arguments
/// * `p` - the parser
/// * `allow_empty` - whether no parse should be considered successful.
/// * `separator` - the separator to be used between parses. Use the `no_separator`/`separator`
///                 functions to construct this parameter.
#[inline]
pub fn many<I: SliceLike, O, O2, S>(p: impl Parser<I, O, S>,
                                    allow_empty: bool,
                                    separator: Option<(bool, impl Parser<I, O2, S>)>,
) -> impl Parser<I, I, S> {
    create_parser!(s, {
        let old_input = s.input;
        many_internal(s, p, |_| {}, allow_empty, separator)
            .map(move |_| old_input.slice_to(old_input.slice_len() - s.input.slice_len()))
    })
}

/// Apply a parser until it fails and store the results in a `Vec`.
///
/// ### Arguments
/// * `p` - the parser
/// * `allow_empty` - whether no parse should be considered successful.
/// * `separator` - the separator to be used between parses. Use the `no_separator`/`separator`
///                 functions to construct this parameter.
#[inline]
pub fn many_to_vec<I, O, O2, S>(p: impl Parser<I, O, S>,
                                allow_empty: bool,
                                separator: Option<(bool, impl Parser<I, O2, S>)>,
) -> impl Parser<I, Vec<O>, S> {
    create_parser!(s, {
        let mut vec = vec![];
        many_internal(s, p, |x| vec.push(x), allow_empty, separator)
            .map(move |_| vec)
    })
}

/// Apply a parser until it fails and store the results in a `HashMap`.
/// The parser `p` must have a result type `(K, V)`, where the key `K: Hash + Eq`.
///
/// ### Arguments
/// * `p` - the parser
/// * `allow_empty` - whether no parse should be considered successful.
/// * `separator` - the separator to be used between parses. Use the `no_separator`/`separator`
///                 functions to construct this parameter.
#[inline]
pub fn many_to_map<I, K: Hash + Eq, V, O2, S>(p: impl Parser<I, (K, V), S>,
                                              allow_empty: bool,
                                              separator: Option<(bool, impl Parser<I, O2, S>)>,
) -> impl Parser<I, HashMap<K, V>, S> {
    create_parser!(s, {
        let mut map = HashMap::new();
        many_internal(s, p, |(k, v)| {map.insert(k, v);}, allow_empty, separator)
            .map(move |_| map)
    })
}

/// Apply a parser until it fails and store the results in a `BTreeMap`.
/// The parser `p` must have a result type `(K, V)`, where the key `K: Ord`.
/// This might give better performance than `many_to_map`.
///
/// ### Arguments
/// * `p` - the parser
/// * `allow_empty` - whether no parse should be considered successful.
/// * `separator` - the separator to be used between parses. Use the `no_separator`/`separator`
///                 functions to construct this parameter.
#[inline]
pub fn many_to_map_ordered<I, K: Ord, V, O2, S>(p: impl Parser<I, (K, V), S>,
                                                allow_empty: bool,
                                                separator: Option<(bool, impl Parser<I, O2, S>)>,
) -> impl Parser<I, BTreeMap<K, V>, S> {
    create_parser!(s, {
        let mut map = BTreeMap::new();
        many_internal(s, p, |(k, v)| {map.insert(k, v);}, allow_empty, separator)
            .map(move |_| map)
    })
}

/// Apply a parser repeatedly and accumulate a result in the spirit of fold.
///
/// ### Arguments
/// * `acc` - the accumulator
/// * `p` - the parser
/// * `f` - a function taking the accumulator as `&mut` along with the result of each
///         successful parse
#[inline]
pub fn fold<T: Copy, I, O, S, P: Parser<I, O, S>>(acc: T,
                                                  p: P,
                                                  f: impl Fn(&mut T, O) -> () + Copy
) -> impl Parser<I, T, S> {
    create_parser!(s, {
        let mut acc = acc;
        many_internal(s, p, |x| { f(&mut acc, x) }, true, no_separator())
            .map(move |_| acc)
    })
}

#[cfg(test)]
mod tests {
    use crate::{parsers::{item, empty, item_while}, core::{*}, combinators::{times, middle, many_to_vec, many, no_separator}, number::integer};

    use super::{fold, or, left};

    fn num_parser() -> impl Parser<&'static str, u32, ()> {
        let num = integer();
        or(left(num, item(',')), left(num, empty()))
    }

    #[test]
    fn many_nums_vec() {
        let p = many_to_vec(num_parser(), true, no_separator());
        let res = parse(p, "1,2,3,4").result.unwrap();
        assert_eq!(res, vec![1,2,3,4]);

        let res = parse(p, "").result.unwrap();
        assert_eq!(res, vec![]);

        let p = many_to_vec(num_parser(), false, no_separator());
        let res = parse(p, "").result;
        assert!(res.is_none());
    }

    #[test]
    fn many_nums() {
        let p = many(num_parser(), true, no_separator());
        let res = parse(p, "1,2,3,4").result.unwrap();
        assert_eq!(res, "1,2,3,4");

        let res = parse(p, "").result.unwrap();
        assert_eq!(res, "");

        let p = many(num_parser(), false, no_separator());
        let res = parse(p, "").result;
        assert!(res.is_none());
    }

    #[test]
    fn fold_add() {
        let p = fold(0, num_parser(), |acc, x| *acc += x);
        let res = parse(p, "1,2,3,4,").result.unwrap();
        assert_eq!(res, 10);
    }

    #[test]
    fn times_test() {
        let p = times(4, left(item('1'), item('2')));
        let res = parse(p, "12121212End");
        assert_eq!(res.result.unwrap(), "12121212");
        assert_eq!(res.state, "End");

        let res = parse(p, "121212").result;
        assert!(res.is_none());
    }

    #[test]
    fn recursive_parens() {
        fn in_parens<'a, S>() -> impl Parser<&'a str, &'a str, S> {
            defer_parser!(or(item_while(|c: char| c.is_alphanumeric()), middle(item('('), in_parens(), item(')'))))
        }

        let x = "(((((((((sought)))))))))";

        let res = parse(in_parens(), x);
        assert_eq!(res.result.unwrap(), "sought");
        assert!(res.state.is_empty());
    }
}