summaryrefslogtreecommitdiff
path: root/src/depend/parsers.rs
blob: 26139ea57fff9db0b9e82064d7ef87821ddbb955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use mon::{Parser, tag, whitespace1};

use crate::{
    Parseable,
    atom::Atom,
    depend::{Conditional, Expr},
    useflag::UseFlag,
};

impl<'a> Parseable<'a, &'a str> for Expr {
    type Parser = impl Parser<&'a str, Output = Self>;

    fn parser() -> Self::Parser {
        |it| {
            let all_of_group = Expr::parser()
                .separated_list(whitespace1(), 1..)
                .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
                .map(|exprs| Expr::AllOf(exprs));

            let any_of_group = Expr::parser()
                .separated_list(whitespace1(), 1..)
                .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
                .preceded_by(tag("||").followed_by(whitespace1()))
                .map(|exprs| Expr::AnyOf(exprs));

            let one_of_group = Expr::parser()
                .separated_list(whitespace1(), 1..)
                .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
                .preceded_by(tag("^^").followed_by(whitespace1()))
                .map(|exprs| Expr::OneOf(exprs));

            let conditional_group = Expr::parser()
                .separated_list(whitespace1(), 1..)
                .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
                .preceded_by(Conditional::parser().followed_by(whitespace1()))
                .map(|exprs| Expr::OneOf(exprs));

            Atom::parser()
                .map(|atom| Expr::Atom(atom))
                .or(conditional_group)
                .or(any_of_group)
                .or(all_of_group)
                .or(one_of_group)
                .parse(it)
        }
    }
}

impl<'a> Parseable<'a, &'a str> for Conditional {
    type Parser = impl Parser<&'a str, Output = Self>;

    fn parser() -> Self::Parser {
        UseFlag::parser()
            .preceded_by(tag("!"))
            .followed_by(tag("?"))
            .map(|flag| Conditional::Negative(flag))
            .or(UseFlag::parser()
                .followed_by(tag("?"))
                .map(|flag| Conditional::Positive(flag)))
    }
}

#[cfg(test)]
mod test {

    use mon::input::InputIter;

    use super::*;

    #[test]
    fn test_expr() {
        let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )");

        Expr::parser()
            .separated_list(whitespace1(), 0..)
            .check_finished(it)
            .unwrap();
    }
}