gobble/
combi.rs

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