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
80
81
82
use super::super::{combinator::*, expression::*, identifier::*};
use crate::ast::*;

/// 338 where_clause = WHERE [domain_rule] `;` { [domain_rule] `;` } .
pub fn where_clause(input: &str) -> ParseResult<WhereClause> {
    tuple((tag("WHERE"), many0(tuple((domain_rule, char(';'))))))
        .map(|(_where, rules)| {
            let rules = rules.into_iter().map(|(rule, _semicolon)| rule).collect();
            WhereClause { rules }
        })
        .parse(input)
}

/// 202 domain_rule = \[ [rule_label_id] `:` \] [expression] .
pub fn domain_rule(input: &str) -> ParseResult<DomainRule> {
    tuple((opt(tuple((rule_label_id, char(':')))), expression))
        .map(|(opt, expr)| {
            let label = opt.map(|(label, _colon)| label);
            DomainRule { label, expr }
        })
        .parse(input)
}

#[cfg(test)]
mod tests {
    use nom::Finish;

    #[test]
    fn domain_rule() {
        let (residual, (rule, _remarks)) =
            super::domain_rule("notnegative : a > 0").finish().unwrap();
        assert_eq!(residual, "");
        assert_eq!(rule.label, Some("notnegative".to_string()));
    }

    #[test]
    fn where_clause() {
        let (residual, (w, _remarks)) = super::where_clause(
            r#"
            WHERE
                notnegative : SELF > 0;
            "#
            .trim(),
        )
        .finish()
        .unwrap();
        assert_eq!(residual, "");
        assert_eq!(w.rules.len(), 1);
        assert_eq!(w.rules[0].label, Some("notnegative".to_string()));
    }

    #[test]
    fn where_clause_complex() {
        let (residual, (w, _remarks)) = super::where_clause(
            r#"
            WHERE
                wr1: (1 <= SELF) AND (SELF <= 12);
            "#
            .trim(),
        )
        .finish()
        .unwrap();
        assert_eq!(residual, "");
        assert_eq!(w.rules.len(), 1);
        assert_eq!(w.rules[0].label, Some("wr1".to_string()));
    }

    #[test]
    fn where_clause3() {
        let (residual, (w, _remarks)) = super::where_clause(
            r#"
            WHERE
                wr1 : VALUE_UNIQUE(s);
            "#
            .trim(),
        )
        .finish()
        .unwrap();
        assert_eq!(residual, "");
        dbg!(w);
    }
}