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