intuicio_parser/
repeat.rs

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