espr/parser/
subsuper.rs

1use super::{combinator::*, identifier::*};
2use crate::ast::*;
3
4/// 164 abstract_entity_declaration = ABSTRACT .
5pub fn abstract_entity_declaration(input: &str) -> ParseResult<Constraint> {
6    tag("ABSTRACT")
7        .map(|_| Constraint::AbstractEntity)
8        .parse(input)
9}
10
11/// 166 abstract_supertype_declaration = ABSTRACT SUPERTYPE \[ [subtype_constraint] \] .
12pub fn abstract_supertype_declaration(input: &str) -> ParseResult<Constraint> {
13    tuple((tag("ABSTRACT"), tag("SUPERTYPE"), opt(subtype_constraint)))
14        .map(|(_abstract, _supertype, expr)| Constraint::AbstractSuperType(expr))
15        .parse(input)
16}
17
18/// 312 subsuper = \[ [supertype_constraint] \] \[ [subtype_declaration] \] .
19pub fn subsuper(input: &str) -> ParseResult<(Option<Constraint>, Option<SubTypeDecl>)> {
20    tuple((opt(supertype_constraint), opt(subtype_declaration))).parse(input)
21}
22
23/// 318 subtype_declaration = SUBTYPE OF `(` [entity_ref] { `,` [entity_ref] } `)` .
24pub fn subtype_declaration(input: &str) -> ParseResult<SubTypeDecl> {
25    tuple((
26        tag("SUBTYPE"),
27        tag("OF"),
28        char('('),
29        comma_separated(entity_ref),
30        char(')'),
31    ))
32    .map(|(_subtype, _of, _open, entity_references, _close)| SubTypeDecl { entity_references })
33    .parse(input)
34}
35
36/// 313 subtype_constraint = OF `(` [supertype_expression] `)` .
37pub fn subtype_constraint(input: &str) -> ParseResult<SuperTypeExpression> {
38    tuple((tag("OF"), char('('), supertype_expression, char(')')))
39        .map(|(_of, _open, expr, _close)| expr)
40        .parse(input)
41}
42
43/// 319 supertype_constraint = [abstract_entity_declaration] | [abstract_supertype_declaration] | [supertype_rule] .
44pub fn supertype_constraint(input: &str) -> ParseResult<Constraint> {
45    alt((
46        abstract_supertype_declaration,
47        abstract_entity_declaration,
48        supertype_rule,
49    ))
50    .parse(input)
51}
52
53/// 320 supertype_expression = [supertype_factor] { ANDOR [supertype_factor] } .
54pub fn supertype_expression(input: &str) -> ParseResult<SuperTypeExpression> {
55    tuple((
56        supertype_factor,
57        many0(tuple((tag("ANDOR"), supertype_factor))),
58    ))
59    .map(|(first, tails)| {
60        if !tails.is_empty() {
61            let mut factors = vec![first];
62            for (_andor, factor) in tails {
63                factors.push(factor)
64            }
65            SuperTypeExpression::AndOr { factors }
66        } else {
67            first
68        }
69    })
70    .parse(input)
71}
72
73/// 321 supertype_factor = [supertype_term] { AND [supertype_term] } .
74pub fn supertype_factor(input: &str) -> ParseResult<SuperTypeExpression> {
75    tuple((supertype_term, many0(tuple((tag("AND"), supertype_term)))))
76        .map(|(first, tails)| {
77            if !tails.is_empty() {
78                let mut terms = vec![first];
79                for (_and, term) in tails {
80                    terms.push(term)
81                }
82                SuperTypeExpression::And { terms }
83            } else {
84                first
85            }
86        })
87        .parse(input)
88}
89
90/// 323 supertype_term = [entity_ref] | [one_of] | `(` [supertype_expression] `)` .
91pub fn supertype_term(input: &str) -> ParseResult<SuperTypeExpression> {
92    let expr =
93        tuple((char('('), supertype_expression, char(')'))).map(|(_open, expr, _close)| expr);
94    alt((entity_ref.map(SuperTypeExpression::Reference), one_of, expr)).parse(input)
95}
96
97/// 322 supertype_rule = SUPERTYPE [subtype_constraint] .
98pub fn supertype_rule(input: &str) -> ParseResult<Constraint> {
99    tuple((tag("SUPERTYPE"), subtype_constraint))
100        .map(|(_supertype, constraint)| Constraint::SuperTypeRule(constraint))
101        .parse(input)
102}
103
104/// 263 one_of = ONEOF `(` [supertype_expression] { `,` [supertype_expression] } `)` .
105pub fn one_of(input: &str) -> ParseResult<SuperTypeExpression> {
106    tuple((
107        tag("ONEOF"),
108        char('('),
109        comma_separated(supertype_expression),
110        char(')'),
111    ))
112    .map(|(_oneof, _open, exprs, _close)| SuperTypeExpression::OneOf { exprs })
113    .parse(input)
114}
115
116/// 315 subtype_constraint_decl = [subtype_constraint_head] [subtype_constraint_body] END_SUBTYPE_CONSTRAINT `;` .
117pub fn subtype_constraint_decl(input: &str) -> ParseResult<SubTypeConstraint> {
118    tuple((
119        subtype_constraint_head,
120        subtype_constraint_body,
121        tag("END_SUBTYPE_CONSTRAINT"),
122        char(';'),
123    ))
124    .map(
125        |((name, entity), (is_abstract, total_over, expr), _end, _semicolon)| SubTypeConstraint {
126            name,
127            entity,
128            is_abstract,
129            total_over,
130            expr,
131        },
132    )
133    .parse(input)
134}
135
136/// 316 subtype_constraint_head = SUBTYPE_CONSTRAINT [subtype_constraint_id] FOR [entity_ref] `;` .
137pub fn subtype_constraint_head(input: &str) -> ParseResult<(String, String)> {
138    tuple((
139        tag("SUBTYPE_CONSTRAINT"),
140        subtype_constraint_id,
141        tag("FOR"),
142        entity_ref,
143        char(';'),
144    ))
145    .map(|(_start, id, _for, entity, _semicolon)| (id, entity))
146    .parse(input)
147}
148
149/// 314 subtype_constraint_body = \[ [abstract_supertype] \] \[ [total_over] \] \[ [supertype_expression] `;` \] .
150pub fn subtype_constraint_body(
151    input: &str,
152) -> ParseResult<(bool, Option<Vec<String>>, Option<SuperTypeExpression>)> {
153    tuple((
154        opt(abstract_supertype).map(|opt| opt.is_some()),
155        opt(total_over),
156        opt(tuple((supertype_expression, char(';'))).map(|(expr, _semicolon)| expr)),
157    ))
158    .parse(input)
159}
160
161/// 326 total_over = TOTAL_OVER `(` [entity_ref] { `,` [entity_ref] } `)` `;` .
162pub fn total_over(input: &str) -> ParseResult<Vec<String>> {
163    tuple((
164        tag("TOTAL_OVER"),
165        char('('),
166        many1(entity_ref),
167        char(')'),
168        char(';'),
169    ))
170    .map(|(_start, _open, references, _close, _semicolon)| references)
171    .parse(input)
172}
173
174/// 165 abstract_supertype = ABSTRACT SUPERTYPE `;` .
175pub fn abstract_supertype(input: &str) -> ParseResult<()> {
176    tuple((tag("ABSTRACT"), tag("SUPERTYPE"), char(';')))
177        .map(|(_abstract, _supertype, _semicolon)| ())
178        .parse(input)
179}
180
181#[cfg(test)]
182mod tests {
183    use nom::Finish;
184
185    #[test]
186    fn subtype_constraint_oneof() {
187        let exp_str = r#"
188        SUBTYPE_CONSTRAINT separate_species FOR pet;
189          ABSTRACT SUPERTYPE;
190          ONEOF(cat, rabbit, dog);
191        END_SUBTYPE_CONSTRAINT;
192        "#
193        .trim();
194
195        let (residual, (entity, _remark)) =
196            super::subtype_constraint_decl(exp_str).finish().unwrap();
197        dbg!(&entity);
198        assert_eq!(residual, "");
199    }
200}