intuicio_parser/
repeat.rs1use 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(®istry, "foofoofoo").unwrap();
59 assert_eq!(rest, "");
60 assert_eq!(result.consume::<Vec<ParserOutput>>().ok().unwrap().len(), 3);
61 assert_eq!(
62 format!("{}", sentence.parse(®istry, "foo").err().unwrap()),
63 "Expected 'foo'"
64 );
65 }
66}