|
@@ -23,6 +23,13 @@ pub trait Parser<'a, R>: Sized {
|
|
|
{
|
|
|
Or { p1: self, p2: other, _phantom: PhantomData }
|
|
|
}
|
|
|
+
|
|
|
+ fn then<NextParser, NextR>(self, next: NextParser) -> Then<'a, Self, NextParser, R, NextR>
|
|
|
+ where
|
|
|
+ NextParser: Parser<'a, NextR>,
|
|
|
+ {
|
|
|
+ Then { p1: self, p2: next, _phantom: PhantomData }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
impl<'a, F, R> Parser<'a, R> for F
|
|
@@ -63,18 +70,6 @@ where
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub fn pair<'a, P1, P2, R1, R2>(a: P1, b: P2) -> impl Parser<'a, (R1, R2)>
|
|
|
-where
|
|
|
- P1: Parser<'a, R1>,
|
|
|
- P2: Parser<'a, R2>,
|
|
|
-{
|
|
|
- move |input| {
|
|
|
- a.parse(input).and_then(|(next_input, result_a)| {
|
|
|
- b.parse(next_input).map(|(final_input, result_b)| (final_input, (result_a, result_b)))
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// TODO: can we make this formattable with stuff from the parse result?
|
|
|
pub fn comment<'a, P, R>(parser: P, comment: &'static str) -> impl Parser<'a, R>
|
|
|
where
|
|
@@ -131,6 +126,30 @@ where
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+pub struct Then<'a, P1, P2, R1, R2>
|
|
|
+where
|
|
|
+ P1: Parser<'a, R1>,
|
|
|
+ P2: Parser<'a, R2>,
|
|
|
+{
|
|
|
+ p1: P1,
|
|
|
+ p2: P2,
|
|
|
+ _phantom: PhantomData<&'a (R1, R2)>,
|
|
|
+}
|
|
|
+
|
|
|
+impl<'a, P1, P2, R1, R2> Parser<'a, (R1, R2)> for Then<'a, P1, P2, R1, R2>
|
|
|
+where
|
|
|
+ P1: Parser<'a, R1>,
|
|
|
+ P2: Parser<'a, R2>,
|
|
|
+{
|
|
|
+ fn parse(&self, input: &'a [u8]) -> ParseResult<'a, (R1, R2)> {
|
|
|
+ self.p1.parse(input).and_then(|(next_input, result_a)| {
|
|
|
+ self.p2
|
|
|
+ .parse(next_input)
|
|
|
+ .map(|(final_input, result_b)| (final_input, (result_a, result_b)))
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/// Takes a number of parsers, and tries to apply each one to the input in order. Returns the
|
|
|
/// result of the first one that succeeds, or fails if all of them fail.
|
|
|
pub macro choice {
|