aoc_parse/parsers/
either.rs

1//! Alternation.
2
3use crate::{
4    parsers::{empty, map, EmptyParser, MapParser},
5    types::ParserOutput,
6    ParseContext, ParseIter, Parser, Reported, Result,
7};
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum Either<A, B> {
11    Left(A),
12    Right(B),
13}
14
15#[derive(Copy, Clone)]
16pub struct EitherParser<A, B> {
17    left: A,
18    right: B,
19}
20
21pub struct EitherParseIter<'parse, A, B>
22where
23    A: Parser + 'parse,
24    B: Parser + 'parse,
25{
26    start: usize,
27    parsers: &'parse EitherParser<A, B>,
28    iter: Either<A::Iter<'parse>, B::Iter<'parse>>,
29}
30
31impl<A, B> Parser for EitherParser<A, B>
32where
33    A: Parser,
34    B: Parser,
35{
36    type Output = Either<A::Output, B::Output>;
37    type RawOutput = (Either<A::Output, B::Output>,);
38    type Iter<'parse> = EitherParseIter<'parse, A, B>
39    where
40        A: 'parse,
41        B: 'parse;
42
43    fn parse_iter<'parse>(
44        &'parse self,
45        context: &mut ParseContext<'parse>,
46        start: usize,
47    ) -> Result<Self::Iter<'parse>, Reported> {
48        let iter = match self.left.parse_iter(context, start) {
49            Ok(iter) => Either::Left(iter),
50            Err(Reported) => Either::Right(self.right.parse_iter(context, start)?),
51        };
52        Ok(EitherParseIter {
53            start,
54            parsers: self,
55            iter,
56        })
57    }
58}
59
60impl<'parse, A, B> ParseIter<'parse> for EitherParseIter<'parse, A, B>
61where
62    A: Parser,
63    B: Parser,
64{
65    type RawOutput = (Either<A::Output, B::Output>,);
66
67    fn match_end(&self) -> usize {
68        match &self.iter {
69            Either::Left(iter) => iter.match_end(),
70            Either::Right(iter) => iter.match_end(),
71        }
72    }
73
74    fn backtrack(&mut self, context: &mut ParseContext<'parse>) -> Result<(), Reported> {
75        match &mut self.iter {
76            Either::Left(iter) => {
77                if iter.backtrack(context).is_ok() {
78                    return Ok(());
79                }
80                self.iter = Either::Right(self.parsers.right.parse_iter(context, self.start)?);
81                Ok(())
82            }
83            Either::Right(iter) => iter.backtrack(context),
84        }
85    }
86
87    fn convert(&self) -> (Either<A::Output, B::Output>,) {
88        (match &self.iter {
89            Either::Left(iter) => Either::Left(iter.convert().into_user_type()),
90            Either::Right(iter) => Either::Right(iter.convert().into_user_type()),
91        },)
92    }
93}
94
95pub fn either<A, B>(left: A, right: B) -> EitherParser<A, B> {
96    EitherParser { left, right }
97}
98
99pub type AltParser<A, B, T> =
100    MapParser<EitherParser<A, B>, fn(Either<<A as Parser>::Output, <B as Parser>::Output>) -> T>;
101
102/// Used by the `parser!()` macro to implement `{p1, p2, ...}` syntax.
103#[doc(hidden)]
104pub fn alt<A, B, T>(left: A, right: B) -> AltParser<A, B, T>
105where
106    A: Parser<Output = T>,
107    B: Parser<Output = T>,
108{
109    map(either(left, right), |out| match out {
110        Either::Left(value) => value,
111        Either::Right(value) => value,
112    })
113}
114
115pub type OptParser<P> = AltParser<P, EmptyParser, Option<<P as Parser>::Output>>;
116
117/// Used by the `parser!()` macro to implement the `?` quantifier.
118#[doc(hidden)]
119pub fn opt<P>(pattern: P) -> OptParser<P>
120where
121    P: Parser,
122{
123    map(either(pattern, empty()), |e| match e {
124        Either::Left(left) => Some(left),
125        Either::Right(()) => None,
126    })
127}