1use nom::{
2 branch::alt,
3 bytes::complete::tag,
4 character::complete::{char, line_ending, one_of},
5 combinator::{map_res, recognize},
6 error::{FromExternalError, ParseError},
7 multi::{many0, many1},
8 sequence::delimited,
9 IResult,
10};
11
12// Bind the given parser to the given value (map_res short).
13pub fn bind<'a, F: 'a, T: Copy, O, E: ParseError<&'a str> + FromExternalError<&'a str, ()>>(
14 inner: F,
15 val: T,
16) -> impl FnMut(&'a str) -> IResult<&'a str, T, E>
17where
18 F: FnMut(&'a str) -> IResult<&'a str, O, E>,
19{
20 map_res(inner, move |_| -> Result<T, ()> { Ok(val) })
21}
22
23// Parse on of the given strings and return the given value.
24pub fn str<'a, T: Copy, E: ParseError<&'a str> + FromExternalError<&'a str, ()> + 'a>(
25 name: &'a str,
26 other: &'a str,
27 val: T,
28) -> impl FnMut(&'a str) -> IResult<&'a str, T, E> {
29 bind(alt((tag(name), tag(other))), val)
30}
31
32pub fn digits(input: &str) -> IResult<&str, u32> {
33 map_res(recognize(many1(one_of("0123456789"))), |input: &str| {
34 u32::from_str_radix(input, 10)
35 })(input)
36}
37
38pub fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(
39 inner: F,
40) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
41where
42 F: Fn(&'a str) -> IResult<&'a str, O, E>,
43{
44 delimited(many0(char(' ')), inner, many0(char(' ')))
45}
46
47pub fn empty_lines<'a, F: 'a, O, E: ParseError<&'a str> + 'a>(
48 inner: F,
49) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
50where
51 F: Fn(&'a str) -> IResult<&'a str, O, E>,
52{
53 delimited(many0(ws(line_ending)), inner, many0(ws(line_ending)))
54}