intuicio_parser/
sequence.rs

1use crate::{ParseResult, Parser, ParserExt, ParserHandle, ParserOutput, ParserRegistry};
2
3pub mod shorthand {
4    use super::*;
5
6    pub fn seq(values: impl IntoIterator<Item = ParserHandle>) -> ParserHandle {
7        SequenceParser::from_iter(values).into_handle()
8    }
9
10    pub fn seq_del(
11        delimiter: ParserHandle,
12        values: impl IntoIterator<Item = ParserHandle>,
13    ) -> ParserHandle {
14        let mut result = SequenceDelimitedParser::new(delimiter);
15        for parser in values {
16            result.push(parser);
17        }
18        result.into_handle()
19    }
20}
21
22#[derive(Default, Clone)]
23pub struct SequenceParser {
24    parsers: Vec<ParserHandle>,
25}
26
27impl SequenceParser {
28    pub fn with(mut self, parser: ParserHandle) -> Self {
29        self.push(parser);
30        self
31    }
32
33    pub fn push(&mut self, parser: ParserHandle) {
34        self.parsers.push(parser);
35    }
36}
37
38impl Parser for SequenceParser {
39    fn parse<'a>(&self, registry: &ParserRegistry, mut input: &'a str) -> ParseResult<'a> {
40        let mut result = Vec::with_capacity(self.parsers.len());
41        for parser in &self.parsers {
42            let (new_input, value) = parser.parse(registry, input)?;
43            input = new_input;
44            result.push(value);
45        }
46        Ok((input, ParserOutput::new(result).ok().unwrap()))
47    }
48}
49
50impl FromIterator<ParserHandle> for SequenceParser {
51    fn from_iter<T: IntoIterator<Item = ParserHandle>>(iter: T) -> Self {
52        Self {
53            parsers: iter.into_iter().collect(),
54        }
55    }
56}
57
58#[derive(Clone)]
59pub struct SequenceDelimitedParser {
60    delimiter: ParserHandle,
61    parsers: Vec<ParserHandle>,
62}
63
64impl SequenceDelimitedParser {
65    pub fn new(delimiter: ParserHandle) -> Self {
66        Self {
67            delimiter,
68            parsers: Default::default(),
69        }
70    }
71
72    pub fn with(mut self, parser: ParserHandle) -> Self {
73        self.push(parser);
74        self
75    }
76
77    pub fn push(&mut self, parser: ParserHandle) {
78        self.parsers.push(parser);
79    }
80}
81
82impl Parser for SequenceDelimitedParser {
83    fn parse<'a>(&self, registry: &ParserRegistry, mut input: &'a str) -> ParseResult<'a> {
84        let mut result = Vec::with_capacity(self.parsers.len() * 2);
85        for (index, parser) in self.parsers.iter().enumerate() {
86            if index > 0 {
87                let (new_input, _) = self.delimiter.parse(registry, input)?;
88                input = new_input;
89            }
90            let (new_input, value) = parser.parse(registry, input)?;
91            input = new_input;
92            result.push(value);
93        }
94        Ok((input, ParserOutput::new(result).ok().unwrap()))
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use crate::{
101        sequence::{SequenceDelimitedParser, SequenceParser},
102        shorthand::{lit, seq, seq_del, ws},
103        ParserNoValue, ParserOutput, ParserRegistry,
104    };
105
106    fn is_async<T: Send + Sync>() {}
107
108    #[test]
109    fn test_sequence() {
110        is_async::<SequenceParser>();
111
112        let registry = ParserRegistry::default();
113        let sentence = seq([lit("foo"), ws(), lit("="), ws(), lit("bar")]);
114        let (rest, result) = sentence.parse(&registry, "foo = bar").unwrap();
115        assert_eq!(rest, "");
116        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
117        assert_eq!(result.len(), 5);
118        for result in result {
119            assert!(result.read::<String>().is_some() || result.read::<ParserNoValue>().is_some());
120        }
121        assert_eq!(
122            format!("{}", sentence.parse(&registry, "foo = ").err().unwrap()),
123            "Expected 'bar'"
124        );
125    }
126
127    #[test]
128    fn test_sequence_delimited() {
129        is_async::<SequenceDelimitedParser>();
130
131        let registry = ParserRegistry::default();
132        let sentence = seq_del(ws(), [lit("foo"), lit("="), lit("bar")]);
133        let (rest, result) = sentence.parse(&registry, "foo = bar").unwrap();
134        assert_eq!(rest, "");
135        let result = result.consume::<Vec<ParserOutput>>().ok().unwrap();
136        assert_eq!(result.len(), 3);
137        for result in result {
138            assert!(result.read::<String>().is_some() || result.read::<()>().is_some());
139        }
140        assert_eq!(
141            format!("{}", sentence.parse(&registry, "foo = ").err().unwrap()),
142            "Expected 'bar'"
143        );
144    }
145}