ldscript_parser/
whitespace.rs

1use nom::{
2    branch::alt,
3    bytes::complete::{tag, take_until},
4    character::complete::multispace1,
5    combinator::recognize,
6    multi::{fold_many0, fold_many1},
7    sequence::delimited,
8    IResult,
9};
10
11pub fn comment(input: &str) -> IResult<&str, &str> {
12    delimited(tag("/*"), take_until("*/"), tag("*/"))(input)
13}
14
15pub fn space_or_comment(input: &str) -> IResult<&str, &str> {
16    alt((multispace1, comment))(input)
17}
18
19pub fn space(input: &str) -> IResult<&str, &str> {
20    recognize(fold_many1(space_or_comment, || (), |_, _| ()))(input)
21}
22
23pub fn opt_space(input: &str) -> IResult<&str, &str> {
24    recognize(fold_many0(space_or_comment, || (), |_, _| ()))(input)
25}
26
27/// Transforms a parser to automatically consume whitespace and comments
28/// between each token.
29macro_rules! wsc(
30    ($arg:expr) => ({
31        use $crate::whitespace::opt_space;
32        use nom::sequence::delimited;
33        delimited(opt_space, $arg, opt_space)
34    });
35
36    ($arg0:expr, $($args:expr),+) => ({
37        use $crate::whitespace::opt_space;
38        use nom::sequence::delimited;
39        use nom::sequence::tuple;
40        delimited(opt_space, tuple(($arg0, $($args),*)), opt_space)
41    })
42);
43
44#[cfg(test)]
45mod tests {
46    use nom::{
47        bytes::complete::{tag, take_while1},
48        multi::many0,
49        sequence::tuple,
50    };
51    use whitespace::opt_space;
52
53    fn is_good(c: char) -> bool {
54        c.is_alphanumeric() || c == '/' || c == '*'
55    }
56
57    #[test]
58    fn test_wsc() {
59        let mut test_parser = many0(wsc!(take_while1(is_good)));
60        let input = "a /* b */ c / * d /**/ e ";
61        assert_done!(test_parser(input), vec!["a", "c", "/", "*", "d", "e"]);
62    }
63
64    #[test]
65    fn test_opt_space() {
66        let mut test_parser = tuple((
67            tag("("),
68            opt_space,
69            take_while1(is_good),
70            opt_space,
71            tag(")"),
72        ));
73
74        let input1 = "(  a  )";
75        assert_done!(test_parser(input1));
76
77        let input2 = "(a)";
78        assert_done!(test_parser(input2));
79    }
80}