bogobble/
combi.rs

1use crate::err::*;
2use crate::iter::*;
3use crate::parser::*;
4use std::fmt::Debug;
5
6#[derive(Clone)]
7pub struct Maybe<A>(pub A);
8
9impl<'a, A> Parser<'a> for Maybe<A>
10where
11    A: Parser<'a>,
12{
13    type Out = Option<A::Out>;
14    fn parse(&self, i: &PIter<'a>) -> ParseRes<'a, Self::Out> {
15        match self.0.parse(i) {
16            Ok((ir, v, ex)) => Ok((ir, Some(v), ex)),
17            Err(e) => Ok((i.clone(), None, Some(e))),
18        }
19    }
20}
21
22/// returns an option on whether this item was found A common use would be
23/// looking for a minus on the front of a number
24///
25/// ```rust
26/// use bogobble::*;
27/// use std::str::FromStr;
28/// let p = (maybe("-"),(NumDigit.min_n(1))).try_map(|(m,n)|{
29///     let res:i32 = n.parse().map_err(|e|Expected::Str("[1..9]+"))?;
30///     if m.is_some() {
31///         return Ok(-res )
32///     }
33///     Ok(res)
34/// });
35/// let s = p.parse_s("-34").unwrap();
36/// assert_eq!(s,-34);
37/// let s = p.parse_s("34").unwrap();
38/// assert_eq!(s,34);
39/// ```
40pub fn maybe<'a, P: Parser<'a>>(p: P) -> Maybe<P> {
41    Maybe(p)
42}
43
44pub struct Exists<P> {
45    p: P,
46}
47
48impl<'a, P: Parser<'a>> Parser<'a> for Exists<P> {
49    type Out = bool;
50    fn parse(&self, it: &PIter<'a>) -> ParseRes<'a, bool> {
51        match self.p.parse(it) {
52            Ok((nit, _, e)) => Ok((nit, true, e)),
53            Err(e) => Ok((it.clone(), false, Some(e))),
54        }
55    }
56}
57
58pub fn exists<'a, P: Parser<'a>>(p: P) -> Exists<P> {
59    Exists { p }
60}
61
62#[derive(Clone)]
63pub struct Wrap<A, B> {
64    a: A,
65    b: B,
66}
67
68impl<'a, A, B> Parser<'a> for Wrap<A, B>
69where
70    A: Parser<'a>,
71    B: Parser<'a>,
72{
73    type Out = B::Out;
74    fn parse(&self, i: &PIter<'a>) -> ParseRes<'a, Self::Out> {
75        (self.a.br(), self.b.br(), self.a.br())
76            .parse(i)
77            .map_v(|(_, b, _)| b)
78    }
79}
80
81pub fn wrap<'a, A, B>(a: A, b: B) -> Wrap<A, B>
82where
83    A: Parser<'a>,
84    B: Parser<'a>,
85{
86    Wrap { a, b }
87}
88
89impl<'a, P: Parser<'a, Out = V>, V: Debug> Parser<'a> for FailOn<P> {
90    type Out = ();
91    fn parse(&self, it: &PIter<'a>) -> ParseRes<'a, ()> {
92        match self.0.parse(it) {
93            Ok(_) => it.err_r(Expected::Str("Failon Succeeded")),
94            Err(_) => Ok((it.clone(), (), None)),
95        }
96    }
97}
98
99pub struct FailOn<P>(pub P);
100
101pub fn fail_on<'a, P: Parser<'a>>(p: P) -> FailOn<P> {
102    FailOn(p)
103}
104
105#[derive(PartialEq, Debug, Clone)]
106pub struct PDebugger<P> {
107    p: P,
108    s: &'static str,
109}
110
111pub fn debug<'a, P: Parser<'a>>(p: P, s: &'static str) -> PDebugger<P> {
112    PDebugger { p, s }
113}
114
115impl<'a, P: Parser<'a>> Parser<'a> for PDebugger<P> {
116    type Out = P::Out;
117    fn parse(&self, it: &PIter<'a>) -> ParseRes<'a, Self::Out> {
118        println!("DebuggerPre - {}", self.s);
119        let r = self.p.parse(it);
120        match &r {
121            Ok((nit, _, _)) => {
122                let s = match (it.index(), nit.index()) {
123                    (Some(st), Some(f)) => &it.as_str()[..f - st],
124                    _ => it.as_str(),
125                };
126                println!("Success - {}, \"{}\"", self.s, s);
127            }
128            Err(_) => println!("Fail - {}", self.s),
129        };
130        r
131    }
132}