intuicio_parser/
list.rs

1use crate::{ParseResult, Parser, ParserExt, ParserHandle, ParserOutput, ParserRegistry};
2
3pub mod shorthand {
4    use super::*;
5
6    pub fn list(item: ParserHandle, delimiter: ParserHandle, permissive: bool) -> ParserHandle {
7        ListParser::new(item, delimiter, permissive).into_handle()
8    }
9}
10
11#[derive(Clone)]
12pub struct ListParser {
13    item: ParserHandle,
14    delimiter: ParserHandle,
15    permissive: bool,
16}
17
18impl ListParser {
19    pub fn new(item: ParserHandle, delimiter: ParserHandle, permissive: bool) -> Self {
20        Self {
21            item,
22            delimiter,
23            permissive,
24        }
25    }
26}
27
28impl Parser for ListParser {
29    fn parse<'a>(&self, registry: &ParserRegistry, mut input: &'a str) -> ParseResult<'a> {
30        let mut result = vec![];
31        if let Ok((new_input, value)) = self.item.parse(registry, input) {
32            input = new_input;
33            result.push(value);
34            while let Ok((new_input, _)) = self.delimiter.parse(registry, input) {
35                match self.item.parse(registry, new_input) {
36                    Ok((new_input, value)) => {
37                        input = new_input;
38                        result.push(value);
39                    }
40                    Err(error) => {
41                        if self.permissive {
42                            break;
43                        } else {
44                            return Err(error);
45                        }
46                    }
47                }
48            }
49        }
50        Ok((input, ParserOutput::new(result).ok().unwrap()))
51    }
52
53    fn extend(&self, parser: ParserHandle) {
54        self.item.extend(parser);
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use crate::{
61        list::ListParser,
62        shorthand::{alt, list, lit, ows},
63        ParserOutput, ParserRegistry,
64    };
65
66    fn is_async<T: Send + Sync>() {}
67
68    #[test]
69    fn test_list() {
70        is_async::<ListParser>();
71
72        let registry = ParserRegistry::default();
73        let sentence = list(alt([lit("foo"), lit("bar")]), ows(), true);
74        let (rest, _) = sentence.parse(&registry, "").unwrap();
75        assert_eq!(rest, "");
76        let (rest, result) = sentence.parse(&registry, "foobar foozee").unwrap();
77        assert_eq!(rest, "zee");
78        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
79        assert_eq!(result.len(), 3);
80        assert_eq!(result[0].read::<String>().unwrap().as_str(), "foo");
81        assert_eq!(result[1].read::<String>().unwrap().as_str(), "bar");
82        assert_eq!(result[2].read::<String>().unwrap().as_str(), "foo");
83    }
84}