kalosm_sample/structured_parser/
then.rs

1use std::sync::Arc;
2
3use crate::{CreateParserState, ParseResult, ParseStatus, Parser};
4
5/// State of a sequence parser.
6#[derive(Debug, PartialEq, Eq, Copy, Clone)]
7pub enum SequenceParserState<P1, P2, O1> {
8    /// The first parser is incomplete.
9    FirstParser(P1),
10    /// The first parser is finished, and the second parser is incomplete.
11    SecondParser(P2, O1),
12}
13
14impl<P1, P2, O1> SequenceParserState<P1, P2, O1> {
15    /// Create a new sequence parser state.
16    pub fn new(state1: P1) -> Self {
17        Self::FirstParser(state1)
18    }
19}
20
21impl<P1: Default, P2, O1> Default for SequenceParserState<P1, P2, O1> {
22    fn default() -> Self {
23        SequenceParserState::FirstParser(Default::default())
24    }
25}
26
27impl<P1: CreateParserState, P2: CreateParserState> CreateParserState for SequenceParser<P1, P2> {
28    fn create_parser_state(&self) -> <Self as Parser>::PartialState {
29        SequenceParserState::FirstParser(self.parser1.create_parser_state())
30    }
31}
32
33/// A parser for a sequence of two parsers.
34#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
35pub struct SequenceParser<P1, P2> {
36    parser1: P1,
37    parser2: P2,
38}
39
40impl<P1, P2> SequenceParser<P1, P2> {
41    /// Create a new sequence parser.
42    pub fn new(parser1: P1, parser2: P2) -> Self {
43        Self { parser1, parser2 }
44    }
45}
46
47impl<P1: Parser, P2: CreateParserState> Parser for SequenceParser<P1, P2> {
48    type Output = (P1::Output, P2::Output);
49    type PartialState = SequenceParserState<P1::PartialState, P2::PartialState, P1::Output>;
50
51    fn parse<'a>(
52        &self,
53        state: &Self::PartialState,
54        input: &'a [u8],
55    ) -> crate::ParseResult<ParseStatus<'a, Self::PartialState, Self::Output>> {
56        match state {
57            SequenceParserState::FirstParser(p1) => {
58                let result = self.parser1.parse(p1, input)?;
59                match result {
60                    ParseStatus::Finished {
61                        result: o1,
62                        remaining,
63                    } => {
64                        let second_parser_state = self.parser2.create_parser_state();
65                        let result = self.parser2.parse(&second_parser_state, remaining)?;
66                        match result {
67                            ParseStatus::Finished { result, remaining } => {
68                                Ok(ParseStatus::Finished {
69                                    result: (o1, result),
70                                    remaining,
71                                })
72                            }
73                            ParseStatus::Incomplete {
74                                new_state: p2,
75                                required_next,
76                            } => {
77                                let new_state = SequenceParserState::SecondParser(p2, o1);
78                                Ok(ParseStatus::Incomplete {
79                                    new_state,
80                                    required_next,
81                                })
82                            }
83                        }
84                    }
85                    ParseStatus::Incomplete {
86                        new_state: p1,
87                        required_next,
88                    } => {
89                        let new_state = SequenceParserState::FirstParser(p1);
90                        Ok(ParseStatus::Incomplete {
91                            new_state,
92                            required_next,
93                        })
94                    }
95                }
96            }
97            SequenceParserState::SecondParser(p2, o1) => {
98                let result = self.parser2.parse(p2, input)?;
99                match result {
100                    ParseStatus::Finished { result, remaining } => Ok(ParseStatus::Finished {
101                        result: (o1.clone(), result),
102                        remaining,
103                    }),
104                    ParseStatus::Incomplete {
105                        new_state: p2,
106                        required_next,
107                    } => {
108                        let new_state = SequenceParserState::SecondParser(p2, o1.clone());
109                        Ok(ParseStatus::Incomplete {
110                            new_state,
111                            required_next,
112                        })
113                    }
114                }
115            }
116        }
117    }
118}
119
120#[test]
121fn sequence_parser() {
122    use crate::{LiteralParser, LiteralParserOffset};
123    let parser = SequenceParser {
124        parser1: LiteralParser::new("Hello, "),
125        parser2: LiteralParser::new("world!"),
126    };
127    let state = SequenceParserState::FirstParser(LiteralParserOffset::default());
128    assert_eq!(
129        parser.parse(&state, b"Hello, world!"),
130        Ok(ParseStatus::Finished {
131            result: ((), ()),
132            remaining: &[]
133        })
134    );
135    assert_eq!(
136        parser.parse(&state, b"Hello, "),
137        Ok(ParseStatus::Incomplete {
138            new_state: SequenceParserState::SecondParser(LiteralParserOffset::new(0), ()),
139            required_next: "world!".into()
140        })
141    );
142    assert_eq!(
143        parser.parse(
144            &parser
145                .parse(&state, b"Hello, ")
146                .unwrap()
147                .unwrap_incomplete()
148                .0,
149            b"world!"
150        ),
151        Ok(ParseStatus::Finished {
152            result: ((), ()),
153            remaining: &[]
154        })
155    );
156    assert!(parser.parse(&state, b"Goodbye, world!").is_err(),);
157}
158
159/// State of a then lazy parser.
160#[derive(Debug, PartialEq, Eq)]
161pub enum ThenLazyParserState<P1: Parser, P2: Parser> {
162    /// The first parser is incomplete.
163    FirstParser(P1::PartialState),
164    /// The first parser is finished, and the second parser is incomplete.
165    SecondParser {
166        /// The result of the first parser.
167        first_output: P1::Output,
168        /// The second parser.
169        second_parser: Arc<P2>,
170        /// The state of the second parser.
171        second_state: P2::PartialState,
172    },
173}
174
175impl<P1: Parser, P2: Parser> Clone for ThenLazyParserState<P1, P2>
176where
177    P1::PartialState: Clone,
178    P2::PartialState: Clone,
179{
180    fn clone(&self) -> Self {
181        match self {
182            Self::FirstParser(first_state) => Self::FirstParser(first_state.clone()),
183            Self::SecondParser {
184                first_output,
185                second_parser,
186                second_state,
187            } => Self::SecondParser {
188                first_output: first_output.clone(),
189                second_parser: second_parser.clone(),
190                second_state: second_state.clone(),
191            },
192        }
193    }
194}
195
196impl<P1: Parser, P2: Parser> ThenLazyParserState<P1, P2> {
197    /// Create a new then lazy parser state.
198    pub fn new(first_state: P1::PartialState) -> Self {
199        Self::FirstParser(first_state)
200    }
201}
202
203impl<P1: Parser, P2: Parser> Default for ThenLazyParserState<P1, P2>
204where
205    P1::PartialState: Default,
206{
207    fn default() -> Self {
208        Self::FirstParser(Default::default())
209    }
210}
211
212/// A parser that is initialized lazily based on the state of the previous parser.
213pub struct ThenLazy<P1, F> {
214    parser1: P1,
215    parser_fn: F,
216}
217
218impl<P1: Parser, P2: CreateParserState, F: Fn(&P1::Output) -> P2> ThenLazy<P1, F> {
219    /// Create a new parser that is lazily initialized based on the output of the first parser.
220    pub fn new(parser1: P1, parser_fn: F) -> Self {
221        Self { parser1, parser_fn }
222    }
223}
224
225impl<P1: CreateParserState, P2: CreateParserState, F: Fn(&P1::Output) -> P2> CreateParserState
226    for ThenLazy<P1, F>
227{
228    fn create_parser_state(&self) -> <Self as Parser>::PartialState {
229        ThenLazyParserState::FirstParser(self.parser1.create_parser_state())
230    }
231}
232
233impl<P1: Parser, P2: CreateParserState, F: Fn(&P1::Output) -> P2> Parser for ThenLazy<P1, F> {
234    type Output = (P1::Output, P2::Output);
235    type PartialState = ThenLazyParserState<P1, P2>;
236
237    fn parse<'a>(
238        &self,
239        state: &Self::PartialState,
240        input: &'a [u8],
241    ) -> ParseResult<ParseStatus<'a, Self::PartialState, Self::Output>> {
242        match state {
243            ThenLazyParserState::FirstParser(p1) => {
244                let result = self.parser1.parse(p1, input)?;
245                match result {
246                    ParseStatus::Finished {
247                        result: o1,
248                        remaining,
249                    } => {
250                        let parser2 = Arc::new((self.parser_fn)(&o1));
251                        let second_parser_state = parser2.create_parser_state();
252                        let result = parser2.parse(&second_parser_state, remaining)?;
253                        match result {
254                            ParseStatus::Finished { result, remaining } => {
255                                Ok(ParseStatus::Finished {
256                                    result: (o1, result),
257                                    remaining,
258                                })
259                            }
260                            ParseStatus::Incomplete {
261                                new_state: p2,
262                                required_next,
263                            } => {
264                                let new_state = ThenLazyParserState::SecondParser {
265                                    first_output: o1.clone(),
266                                    second_parser: parser2.clone(),
267                                    second_state: p2,
268                                };
269                                Ok(ParseStatus::Incomplete {
270                                    new_state,
271                                    required_next,
272                                })
273                            }
274                        }
275                    }
276                    ParseStatus::Incomplete {
277                        new_state: p1,
278                        required_next,
279                    } => {
280                        let new_state = ThenLazyParserState::FirstParser(p1);
281                        Ok(ParseStatus::Incomplete {
282                            new_state,
283                            required_next,
284                        })
285                    }
286                }
287            }
288            ThenLazyParserState::SecondParser {
289                first_output,
290                second_parser,
291                second_state,
292            } => {
293                let result = second_parser.parse(second_state, input)?;
294                match result {
295                    ParseStatus::Finished { result, remaining } => Ok(ParseStatus::Finished {
296                        result: (first_output.clone(), result),
297                        remaining,
298                    }),
299                    ParseStatus::Incomplete {
300                        new_state: p2,
301                        required_next,
302                    } => {
303                        let new_state = ThenLazyParserState::SecondParser {
304                            first_output: first_output.clone(),
305                            second_parser: second_parser.clone(),
306                            second_state: p2,
307                        };
308                        Ok(ParseStatus::Incomplete {
309                            new_state,
310                            required_next,
311                        })
312                    }
313                }
314            }
315        }
316    }
317}