intuicio_parser/
list.rs

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