intuicio_parser/
sequence.rs

1use crate::{
2    ParseResult, Parser, ParserExt, ParserHandle, ParserNoValue, ParserOutput, ParserRegistry,
3};
4
5pub mod shorthand {
6    use super::*;
7
8    pub fn seq(values: impl IntoIterator<Item = ParserHandle>) -> ParserHandle {
9        SequenceParser::from_iter(values).into_handle()
10    }
11
12    pub fn seq_del(
13        delimiter: ParserHandle,
14        values: impl IntoIterator<Item = ParserHandle>,
15    ) -> ParserHandle {
16        let mut result = SequenceDelimitedParser::new(delimiter);
17        for parser in values {
18            result.push(parser);
19        }
20        result.into_handle()
21    }
22
23    pub fn seq_inv(values: impl IntoIterator<Item = ParserHandle>) -> ParserHandle {
24        SequenceParser::from_iter(values)
25            .ignore_no_value(true)
26            .into_handle()
27    }
28
29    pub fn seq_del_inv(
30        delimiter: ParserHandle,
31        values: impl IntoIterator<Item = ParserHandle>,
32    ) -> ParserHandle {
33        let mut result = SequenceDelimitedParser::new(delimiter).ignore_no_value(true);
34        for parser in values {
35            result.push(parser);
36        }
37        result.into_handle()
38    }
39}
40
41#[derive(Default, Clone)]
42pub struct SequenceParser {
43    parsers: Vec<ParserHandle>,
44    ignore_no_value: bool,
45}
46
47impl SequenceParser {
48    pub fn with(mut self, parser: ParserHandle) -> Self {
49        self.push(parser);
50        self
51    }
52
53    pub fn ignore_no_value(mut self, ignore: bool) -> Self {
54        self.ignore_no_value = ignore;
55        self
56    }
57
58    pub fn push(&mut self, parser: ParserHandle) {
59        self.parsers.push(parser);
60    }
61}
62
63impl Parser for SequenceParser {
64    fn parse<'a>(&self, registry: &ParserRegistry, mut input: &'a str) -> ParseResult<'a> {
65        let mut result = Vec::with_capacity(self.parsers.len());
66        for parser in &self.parsers {
67            let (new_input, value) = parser.parse(registry, input)?;
68            input = new_input;
69            if !self.ignore_no_value || !value.is::<ParserNoValue>() {
70                result.push(value);
71            }
72        }
73        Ok((input, ParserOutput::new(result).ok().unwrap()))
74    }
75}
76
77impl FromIterator<ParserHandle> for SequenceParser {
78    fn from_iter<T: IntoIterator<Item = ParserHandle>>(iter: T) -> Self {
79        Self {
80            parsers: iter.into_iter().collect(),
81            ignore_no_value: false,
82        }
83    }
84}
85
86#[derive(Clone)]
87pub struct SequenceDelimitedParser {
88    delimiter: ParserHandle,
89    parsers: Vec<ParserHandle>,
90    ignore_no_value: bool,
91}
92
93impl SequenceDelimitedParser {
94    pub fn new(delimiter: ParserHandle) -> Self {
95        Self {
96            delimiter,
97            parsers: Default::default(),
98            ignore_no_value: false,
99        }
100    }
101
102    pub fn with(mut self, parser: ParserHandle) -> Self {
103        self.push(parser);
104        self
105    }
106
107    pub fn ignore_no_value(mut self, ignore: bool) -> Self {
108        self.ignore_no_value = ignore;
109        self
110    }
111
112    pub fn push(&mut self, parser: ParserHandle) {
113        self.parsers.push(parser);
114    }
115}
116
117impl Parser for SequenceDelimitedParser {
118    fn parse<'a>(&self, registry: &ParserRegistry, mut input: &'a str) -> ParseResult<'a> {
119        let mut result = Vec::with_capacity(self.parsers.len() * 2);
120        for (index, parser) in self.parsers.iter().enumerate() {
121            if index > 0 {
122                let (new_input, _) = self.delimiter.parse(registry, input)?;
123                input = new_input;
124            }
125            let (new_input, value) = parser.parse(registry, input)?;
126            input = new_input;
127            if !self.ignore_no_value || !value.is::<ParserNoValue>() {
128                result.push(value);
129            }
130        }
131        Ok((input, ParserOutput::new(result).ok().unwrap()))
132    }
133}
134
135#[cfg(test)]
136mod tests {
137    use crate::{
138        ParserNoValue, ParserOutput, ParserRegistry,
139        sequence::{SequenceDelimitedParser, SequenceParser},
140        shorthand::{erase, lit, seq, seq_del, seq_del_inv, seq_inv, ws},
141    };
142
143    fn is_async<T: Send + Sync>() {}
144
145    #[test]
146    fn test_sequence() {
147        is_async::<SequenceParser>();
148
149        let registry = ParserRegistry::default();
150        let sentence = seq([lit("foo"), ws(), lit("="), ws(), lit("bar")]);
151        let (rest, result) = sentence.parse(&registry, "foo = bar").unwrap();
152        assert_eq!(rest, "");
153        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
154        assert_eq!(result.len(), 5);
155        for result in result {
156            assert!(result.read::<String>().is_some() || result.read::<ParserNoValue>().is_some());
157        }
158        assert_eq!(
159            format!("{}", sentence.parse(&registry, "foo = ").err().unwrap()),
160            "Expected 'bar'"
161        );
162
163        let sentence = seq_inv([lit("foo"), ws(), lit("="), ws(), lit("bar")]);
164        let (rest, result) = sentence.parse(&registry, "foo = bar").unwrap();
165        assert_eq!(rest, "");
166        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
167        assert_eq!(result.len(), 3);
168        for result in result {
169            assert!(result.read::<String>().is_some());
170        }
171        assert_eq!(
172            format!("{}", sentence.parse(&registry, "foo = ").err().unwrap()),
173            "Expected 'bar'"
174        );
175    }
176
177    #[test]
178    fn test_sequence_delimited() {
179        is_async::<SequenceDelimitedParser>();
180
181        let registry = ParserRegistry::default();
182        let sentence = seq_del(ws(), [lit("foo"), lit("="), lit("bar")]);
183        let (rest, result) = sentence.parse(&registry, "foo = bar").unwrap();
184        assert_eq!(rest, "");
185        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
186        assert_eq!(result.len(), 3);
187        for result in result {
188            assert!(result.read::<String>().is_some() || result.read::<()>().is_some());
189        }
190        assert_eq!(
191            format!("{}", sentence.parse(&registry, "foo = ").err().unwrap()),
192            "Expected 'bar'"
193        );
194
195        let sentence = seq_del_inv(ws(), [erase(lit("foo")), lit("="), lit("bar")]);
196        let (rest, result) = sentence.parse(&registry, "foo = bar").unwrap();
197        assert_eq!(rest, "");
198        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
199        assert_eq!(result.len(), 2);
200        for result in result {
201            assert!(result.read::<String>().is_some());
202        }
203        assert_eq!(
204            format!("{}", sentence.parse(&registry, "foo = ").err().unwrap()),
205            "Expected 'bar'"
206        );
207    }
208}