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(®istry, "").unwrap();
75 assert_eq!(rest, "");
76 let (rest, result) = sentence.parse(®istry, "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}