xrust/parser/combinators/
list.rs1use crate::item::Node;
2use crate::parser::{ParseError, ParseInput, StaticState};
3use qualname::{NamespacePrefix, NamespaceUri};
4
5pub fn separated_list0<'a, P1, P2, R1, N: Node, L>(
6 sep: P1,
7 f: P2,
8) -> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Vec<R1>), ParseError>
9where
10 P1: Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, ()), ParseError>,
11 P2: Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, R1), ParseError>,
12 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
13{
14 move |mut input, ss| {
15 let mut res = Vec::new();
16
17 match f(input.clone(), ss) {
18 Err(_e) => {
19 return Ok((input, res));
20 }
21 Ok((i1, o)) => {
22 res.push(o);
23 input = i1;
24 }
25 }
26
27 loop {
28 match sep(input.clone(), ss) {
29 Err(ParseError::Combinator(_)) => {
30 return Ok((input, res));
31 }
32 Err(e) => return Err(e),
33 Ok((i1, _)) => {
34 match f(i1, ss) {
41 Err(ParseError::Combinator(_)) => return Ok((input, res)),
42 Err(e) => return Err(e),
43 Ok((i2, o)) => {
44 res.push(o);
45 input = i2;
46 }
47 }
48 }
49 }
50 }
51 }
52}
53
54pub(crate) fn separated_list1<'a, P1, P2, R1, N: Node, L>(
55 sep: P1,
56 f: P2,
57) -> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Vec<R1>), ParseError>
58where
59 P1: Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, ()), ParseError>,
60 P2: Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, R1), ParseError>,
61 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
62{
63 move |mut input, ss| {
64 let mut res = Vec::new();
65
66 match f(input.clone(), ss) {
67 Err(e) => return Err(e),
68 Ok((i1, o)) => {
69 res.push(o);
70 input = i1;
71 }
72 }
73
74 loop {
75 match sep(input.clone(), ss) {
76 Err(ParseError::Combinator(_)) => {
77 return Ok((input, res));
78 }
79 Err(e) => return Err(e),
80 Ok((i1, _)) => {
81 match f(i1, ss) {
88 Err(ParseError::Combinator(_)) => {
89 return Ok((input, res));
90 }
91 Err(e) => return Err(e),
92 Ok((i2, o)) => {
93 res.push(o);
94 input = i2;
95 }
96 }
97 }
98 }
99 }
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use crate::parser::combinators::alt::alt4;
106 use crate::parser::combinators::list::{separated_list0, separated_list1};
107 use crate::parser::combinators::map::map;
108 use crate::parser::combinators::tag::tag;
109 use crate::parser::{ParseError, ParserState, StaticStateBuilder};
110 use crate::trees::nullo::Nullo;
111 use qualname::NamespaceUri;
112
113 #[test]
114 fn parser_separated_list0_test1() {
115 let testdoc = "b";
116 let teststate: ParserState<Nullo> = ParserState::new();
117 let mut static_state = StaticStateBuilder::new()
118 .namespace(|_| {
119 NamespaceUri::try_from("urn:xrust").map_err(|_| ParseError::MissingNameSpace)
120 })
121 .build();
122 let parse_doc = separated_list0(tag(","), map(tag("a"), |_| "a"));
123
124 assert_eq!(
125 Ok((("b", ParserState::new()), vec![])),
126 parse_doc((testdoc, teststate), &mut static_state)
127 );
128 }
129
130 #[test]
131 fn parser_separated_list0_test2() {
132 let testdoc = "a";
133 let teststate: ParserState<Nullo> = ParserState::new();
134 let mut static_state = StaticStateBuilder::new()
135 .namespace(|_| {
136 NamespaceUri::try_from("urn:xrust").map_err(|_| ParseError::MissingNameSpace)
137 })
138 .build();
139 let parse_doc = separated_list0(tag(","), map(tag("a"), |_| "a"));
140
141 assert_eq!(
142 Ok((("", ParserState::new()), vec!["a"])),
143 parse_doc((testdoc, teststate), &mut static_state)
144 );
145 }
146
147 #[test]
148 fn parser_separated_list0_test3() {
149 let testdoc = "a,b,c,d";
150 let teststate: ParserState<Nullo> = ParserState::new();
151 let mut static_state = StaticStateBuilder::new()
152 .namespace(|_| {
153 NamespaceUri::try_from("urn:xrust").map_err(|_| ParseError::MissingNameSpace)
154 })
155 .build();
156 let parse_doc = separated_list1(
157 tag(","),
158 alt4(
159 map(tag("a"), |_| "1"),
160 map(tag("b"), |_| "2"),
161 map(tag("c"), |_| "3"),
162 map(tag("d"), |_| "4"),
163 ),
164 );
165
166 assert_eq!(
167 Ok((("", ParserState::new()), vec!["1", "2", "3", "4"])),
168 parse_doc((testdoc, teststate), &mut static_state)
169 );
170 }
171
172 #[test]
173 fn parser_separated_list1_test1() {
174 let testdoc = "a";
175 let teststate: ParserState<Nullo> = ParserState::new();
176 let mut static_state = StaticStateBuilder::new()
177 .namespace(|_| {
178 NamespaceUri::try_from("urn:xrust").map_err(|_| ParseError::MissingNameSpace)
179 })
180 .build();
181 let parse_doc = separated_list1(tag(","), map(tag("a"), |_| "a"));
182
183 assert_eq!(
184 Ok((("", ParserState::new()), vec!["a"])),
185 parse_doc((testdoc, teststate), &mut static_state)
186 );
187 }
188
189 #[test]
190 fn parser_separated_list1_test2() {
191 let testdoc = "a,b,c,d";
192 let teststate: ParserState<Nullo> = ParserState::new();
193 let mut static_state = StaticStateBuilder::new()
194 .namespace(|_| {
195 NamespaceUri::try_from("urn:xrust").map_err(|_| ParseError::MissingNameSpace)
196 })
197 .build();
198 let parse_doc = separated_list1(
199 tag(","),
200 alt4(
201 map(tag("a"), |_| "1"),
202 map(tag("b"), |_| "2"),
203 map(tag("c"), |_| "3"),
204 map(tag("d"), |_| "4"),
205 ),
206 );
207
208 assert_eq!(
209 Ok((("", ParserState::new()), vec!["1", "2", "3", "4"])),
210 parse_doc((testdoc, teststate), &mut static_state)
211 );
212 }
213}