intuicio_parser/
one_or_more.rs

1use crate::{ParseResult, Parser, ParserExt, ParserHandle, ParserOutput, ParserRegistry};
2
3pub mod shorthand {
4    use super::*;
5
6    pub fn oom(parser: ParserHandle) -> ParserHandle {
7        OneOrMoreParser::new(parser).into_handle()
8    }
9}
10
11#[derive(Clone)]
12pub struct OneOrMoreParser(ParserHandle);
13
14impl OneOrMoreParser {
15    pub fn new(parser: ParserHandle) -> Self {
16        Self(parser)
17    }
18}
19
20impl Parser for OneOrMoreParser {
21    fn parse<'a>(&self, registry: &ParserRegistry, mut input: &'a str) -> ParseResult<'a> {
22        let (new_input, value) = self.0.parse(registry, input)?;
23        input = new_input;
24        let mut result = vec![value];
25        while let Ok((new_input, value)) = self.0.parse(registry, input) {
26            result.push(value);
27            input = new_input;
28        }
29        Ok((input, ParserOutput::new(result).ok().unwrap()))
30    }
31
32    fn extend(&self, parser: ParserHandle) {
33        self.0.extend(parser);
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use crate::{
40        one_or_more::OneOrMoreParser,
41        shorthand::{lit, oom},
42        ParserOutput, ParserRegistry,
43    };
44
45    fn is_async<T: Send + Sync>() {}
46
47    #[test]
48    fn test_one_or_more() {
49        is_async::<OneOrMoreParser>();
50
51        let registry = ParserRegistry::default();
52        let sentence = oom(lit("foo"));
53        let (rest, result) = sentence.parse(&registry, "foofoofoo").unwrap();
54        assert_eq!(rest, "");
55        assert_eq!(result.consume::<Vec<ParserOutput>>().ok().unwrap().len(), 3);
56        assert_eq!(
57            format!("{}", sentence.parse(&registry, " asd ").err().unwrap()),
58            "Expected 'foo'"
59        );
60    }
61}