1use nom::{
14 IResult, Parser,
15 branch::alt,
16 bytes::complete::tag,
17 character::complete::{char, multispace0, multispace1, none_of},
18 combinator::{not, opt, peek, value},
19 multi::{many0, many1},
20};
21use nom_language::error::VerboseError;
22
23pub type ParseResult<'a, X> = IResult<&'a str, X, VerboseError<&'a str>>;
25
26pub trait ExchangeParser<'a, X>:
28 Clone + nom::Parser<&'a str, Output = X, Error = VerboseError<&'a str>>
29{
30}
31
32impl<'a, X, T> ExchangeParser<'a, X> for T where
33 T: Clone + nom::Parser<&'a str, Output = X, Error = VerboseError<&'a str>>
34{
35}
36
37pub fn char_<'a>(c: char) -> impl ExchangeParser<'a, char> {
38 move |input| {
39 let (input, c) = nom::character::complete::char(c).parse(input)?;
40 Ok((input, c))
41 }
42}
43
44pub fn tag_<'a>(name: &'static str) -> impl ExchangeParser<'a, &'a str> {
45 move |input| {
46 let (input, c) = nom::bytes::complete::tag(name).parse(input)?;
47 Ok((input, c))
48 }
49}
50
51pub fn opt_<'a, O>(
52 f: impl ExchangeParser<'a, O>,
53) -> impl ExchangeParser<'a, Option<O>> {
54 move |input| {
55 let (input, c) = nom::combinator::opt(f.clone()).parse(input)?;
56 Ok((input, c))
57 }
58}
59
60pub fn comment(input: &str) -> ParseResult<'_, String> {
69 let internal = alt((
70 none_of("*"),
71 tuple((char('*'), peek(not(char('/'))))).map(|(star, _not_slash)| star),
72 ));
73 tuple((tag("/*"), many0(internal), tag("*/")))
74 .map(|(_start, c, _end)| c.into_iter().collect())
75 .parse(input)
76}
77
78pub fn separator(input: &str) -> ParseResult<'_, ()> {
87 let comment = many1(tuple((multispace0, comment, multispace0))).map(|_| ());
88 alt((comment, value((), multispace1))).parse(input)
89}
90
91pub fn many0_<'a, O>(
92 f: impl ExchangeParser<'a, O>,
93) -> impl ExchangeParser<'a, Vec<O>> {
94 move |input| {
95 let (input, first) = opt(f.clone()).parse(input)?;
96 if first.is_none() {
97 return Ok((input, Vec::new()));
98 };
99 let (input, tail) =
100 many0(tuple((ignorable, f.clone())).map(|(_sep, v)| v))
101 .parse(input)?;
102 let first = vec![first.unwrap()];
103 let list = first.into_iter().chain(tail).collect();
104 Ok((input, list))
105 }
106}
107
108pub fn many1_<'a, O>(
109 f: impl ExchangeParser<'a, O>,
110) -> impl ExchangeParser<'a, Vec<O>> {
111 move |input| {
112 tuple((f.clone(), many0(tuple((ignorable, f.clone())))))
113 .map(|(first, tail)| {
114 let first = vec![first];
115 let tail = tail.into_iter().map(|(_sep, val)| val);
116 first.into_iter().chain(tail).collect()
117 })
118 .parse(input)
119 }
120}
121
122pub fn ignorable(input: &str) -> ParseResult<'_, ()> {
123 let comment = many1(tuple((multispace0, comment, multispace0))).map(|_| ());
124 alt((comment, value((), multispace0))).parse(input)
125}
126
127pub fn separated<'a, O>(
128 c: char,
129 f: impl ExchangeParser<'a, O>,
130) -> impl ExchangeParser<'a, Vec<O>> {
131 move |input| {
132 tuple((
133 f.clone(),
134 many0(
135 tuple((ignorable, char(c), ignorable, f.clone()))
136 .map(|(_sep1, _char, _sep2, value)| value),
137 ),
138 ))
139 .map(|(first, mut tails)| {
140 let mut values = vec![first];
141 values.append(&mut tails);
142 values
143 })
144 .parse(input)
145 }
146}
147
148pub fn comma_separated<'a, O>(
149 f: impl ExchangeParser<'a, O>,
150) -> impl ExchangeParser<'a, Vec<O>> {
151 separated(',', f)
152}
153
154pub fn tuple_<'a, O, List: Tuple<'a, O>>(
156 mut l: List,
157) -> impl ExchangeParser<'a, O> {
158 move |input| l.parse(input)
159}
160
161pub trait Tuple<'a, O>: Clone {
163 fn parse(&mut self, input: &'a str) -> ParseResult<'a, O>;
164}
165
166macro_rules! tuple_gen {
169 ($head:ident, $($tail:ident),*) => {
170 tuple(($head.clone(), ignorable, tuple_gen!($($tail),*)))
171 };
172 ($head:ident) => {
173 $head.clone()
174 };
175}
176
177macro_rules! match_gen {
179 ($head:ident, $($tail:ident),*) => {
180 ($head, _, match_gen!($($tail),*))
181 };
182 ($head:ident) => {
183 $head
184 };
185}
186
187macro_rules! impl_tuple {
188 ($($F:ident),*; $($O:ident),*; $($f:ident),*; $($o:ident),*) => {
189 impl<'a, $($F),*, $($O),*> Tuple<'a, ($($O),*)> for ($($F),*)
190 where
191 $( $F: ExchangeParser<'a, $O> ),*
192 {
193 fn parse(&mut self, input: &'a str) -> ParseResult<'a, ($($O),*)> {
194 let ($($f),*) = self;
195 tuple_gen!($($f),*)
196 .map(|match_gen!($($o),*)| ($($o),*))
197 .parse(input)
198 }
199 }
200 };
201}
202
203impl_tuple!(
204 F1, F2;
205 O1, O2;
206 f1, f2;
207 o1, o2
208);
209impl_tuple!(
210 F1, F2, F3;
211 O1, O2, O3;
212 f1, f2, f3;
213 o1, o2, o3
214);
215impl_tuple!(
216 F1, F2, F3, F4;
217 O1, O2, O3, O4;
218 f1, f2, f3, f4;
219 o1, o2, o3, o4
220);
221impl_tuple!(
222 F1, F2, F3, F4, F5;
223 O1, O2, O3, O4, O5;
224 f1, f2, f3, f4, f5;
225 o1, o2, o3, o4, o5
226);
227impl_tuple!(
228 F1, F2, F3, F4, F5, F6;
229 O1, O2, O3, O4, O5, O6;
230 f1, f2, f3, f4, f5, f6;
231 o1, o2, o3, o4, o5, o6
232);
233impl_tuple!(
234 F1, F2, F3, F4, F5, F6, F7;
235 O1, O2, O3, O4, O5, O6, O7;
236 f1, f2, f3, f4, f5, f6, f7;
237 o1, o2, o3, o4, o5, o6, o7
238);
239impl_tuple!(
240 F1, F2, F3, F4, F5, F6, F7, F8;
241 O1, O2, O3, O4, O5, O6, O7, O8;
242 f1, f2, f3, f4, f5, f6, f7, f8;
243 o1, o2, o3, o4, o5, o6, o7, o8
244);
245impl_tuple!(
246 F1, F2, F3, F4, F5, F6, F7, F8, F9;
247 O1, O2, O3, O4, O5, O6, O7, O8, O9;
248 f1, f2, f3, f4, f5, f6, f7, f8, f9;
249 o1, o2, o3, o4, o5, o6, o7, o8, o9
250);
251
252pub fn tuple<T>(parsers: T) -> T {
258 parsers
259}
260
261#[cfg(test)]
262mod tests {
263 use super::*;
264 use crate::parser::basic::digit;
265 use nom::Finish;
266
267 #[test]
268 fn comment() {
269 let (res, c) = super::comment("/*🦀*/").finish().unwrap();
270 assert_eq!(res, "");
271 assert_eq!(c, "🦀");
272
273 let (res, c) = super::comment("/* vim * vim */").finish().unwrap();
274 assert_eq!(res, "");
275 assert_eq!(c, " vim * vim ");
276 }
277
278 #[test]
279 fn separator() {
280 let (res, _sep) = super::separator("/* comment */").finish().unwrap();
281 assert_eq!(res, "");
282
283 let (res, _sep) = super::separator("/* comment1 */ /* comment2 */")
284 .finish()
285 .unwrap();
286 assert_eq!(res, "");
287
288 let (res, _sep) = super::separator(" ").finish().unwrap();
289 assert_eq!(res, "");
290
291 assert!(super::separator("").finish().is_err());
292 }
293
294 fn tuple_digit(input: &str) -> ParseResult<'_, (char, char)> {
295 tuple_((digit, digit)).parse(input)
296 }
297
298 #[test]
299 fn tuple() {
300 let (res, (a, b)) = tuple_digit("1 /* comment */ 2").finish().unwrap();
301 assert_eq!(res, "");
302 assert_eq!(a, '1');
303 assert_eq!(b, '2');
304 }
305
306 #[test]
307 fn tuple_trailing_space() {
308 let (res, (a, b)) = tuple_digit("1 /* comment */ 2 ").finish().unwrap();
310 assert_eq!(res, " ");
311 assert_eq!(a, '1');
312 assert_eq!(b, '2');
313 }
314
315 #[test]
316 fn tuple_head_space() {
317 assert!(tuple_digit(" 1 /* comment */ 2").finish().is_err());
319 }
320
321 fn many0_digit(input: &str) -> ParseResult<'_, Vec<char>> {
322 many0_(digit).parse(input)
323 }
324
325 #[test]
326 fn many0() {
327 let (res, digits) =
328 many0_digit("1 /* comment */ 2 3").finish().unwrap();
329 assert_eq!(res, "");
330 assert_eq!(digits, &['1', '2', '3']);
331
332 let (res, digits) = many0_digit("").finish().unwrap();
334 assert_eq!(res, "");
335 assert!(digits.is_empty());
336
337 let (res, digits) = many1_digit("1").finish().unwrap();
338 assert_eq!(res, "");
339 assert_eq!(digits, &['1']);
340
341 let (res, digits) = many0_digit("1 /* comment */ 2 ").finish().unwrap();
343 assert_eq!(res, " ");
344 assert_eq!(digits, &['1', '2']);
345
346 let (res, digits) = many0_digit(" 1 /* comment */ 2").finish().unwrap();
348 assert_eq!(res, " 1 /* comment */ 2"); assert!(digits.is_empty());
350 }
351
352 fn many1_digit(input: &str) -> ParseResult<'_, Vec<char>> {
353 many1_(digit).parse(input)
354 }
355
356 #[test]
357 fn many1() {
358 let (res, digits) =
359 many1_digit("1 /* comment */ 2 3").finish().unwrap();
360 assert_eq!(res, "");
361 assert_eq!(digits, &['1', '2', '3']);
362
363 assert!(many1_digit("").finish().is_err());
365
366 let (res, digits) = many1_digit("1").finish().unwrap();
367 assert_eq!(res, "");
368 assert_eq!(digits, &['1']);
369
370 let (res, digits) = many1_digit("1 /* comment */ 2 ").finish().unwrap();
372 assert_eq!(res, " ");
373 assert_eq!(digits, &['1', '2']);
374
375 assert!(many1_digit(" 1 /* comment */ 2").finish().is_err());
377 }
378
379 #[test]
380 fn ignorable() {
381 let (res, _) = super::ignorable("").finish().unwrap();
382 assert_eq!(res, "");
383
384 let (res, _) = super::ignorable(" ").finish().unwrap();
385 assert_eq!(res, "");
386
387 let (res, _) = super::ignorable(" ").finish().unwrap();
388 assert_eq!(res, "");
389
390 let (res, _) = super::ignorable("/* comment */").finish().unwrap();
391 assert_eq!(res, "");
392
393 let (res, _) = super::ignorable("/* comment */ ").finish().unwrap();
394 assert_eq!(res, "");
395
396 let (res, _) = super::ignorable(" /* comment */ ").finish().unwrap();
397 assert_eq!(res, "");
398 }
399
400 fn comma_digit(input: &str) -> ParseResult<'_, Vec<char>> {
401 comma_separated(digit).parse(input)
402 }
403
404 #[test]
405 fn comma() {
406 let (res, digits) = comma_digit("1,2").finish().unwrap();
407 assert_eq!(res, "");
408 assert_eq!(digits, &['1', '2']);
409
410 let (res, digits) = comma_digit("1 ,2").finish().unwrap();
411 assert_eq!(res, "");
412 assert_eq!(digits, &['1', '2']);
413
414 let (res, digits) = comma_digit("1, 2").finish().unwrap();
415 assert_eq!(res, "");
416 assert_eq!(digits, &['1', '2']);
417
418 let (res, digits) = comma_digit("1 , 2").finish().unwrap();
419 assert_eq!(res, "");
420 assert_eq!(digits, &['1', '2']);
421 }
422}