Skip to main content

espr/ast/
entity.rs

1//! AST for entity declarations
2
3use crate::{ast::*, parser::*};
4
5/// Parsed result of EXPRESS's ENTITY
6#[derive(Debug, Clone, PartialEq)]
7pub struct Entity {
8    /// Name of this entity type
9    pub name: String,
10
11    /// attribute name and types
12    ///
13    /// Be sure that this "type" is a string, not validated type in this timing
14    pub attributes: Vec<EntityAttribute>,
15
16    pub constraint: Option<Constraint>,
17    pub subtype_of: Option<SubTypeDecl>,
18
19    pub derive_clause: Option<DeriveClause>,
20    pub inverse_clause: Option<InverseClause>,
21    pub unique_clause: Option<UniqueClause>,
22    pub where_clause: Option<WhereClause>,
23}
24
25crate::derive_ast_component!(Entity, entity_decl);
26
27impl Entity {
28    pub fn has_supertype_decl(&self) -> bool {
29        if let Some(c) = &self.constraint {
30            match c {
31                Constraint::AbstractSuperType(..) | Constraint::SuperTypeRule(..) => true,
32                Constraint::AbstractEntity => false,
33            }
34        } else {
35            false
36        }
37    }
38}
39
40/// Intermediate output of [entity_body]
41#[derive(Debug, Clone, PartialEq)]
42pub struct EntityBody {
43    pub attributes: Vec<EntityAttribute>,
44    pub derive_clause: Option<DeriveClause>,
45    pub inverse_clause: Option<InverseClause>,
46    pub unique_clause: Option<UniqueClause>,
47    pub where_clause: Option<WhereClause>,
48}
49
50#[derive(Debug, Clone, PartialEq)]
51pub enum AttributeDecl {
52    Reference(String),
53    Qualified {
54        /// Like `\point`
55        group: String,
56        /// Like `.x`
57        attribute: String,
58        /// For [redeclared_attribute]
59        rename: Option<String>,
60    },
61}
62
63// for easy testing
64impl<'a> PartialEq<&'a str> for AttributeDecl {
65    fn eq(&self, other: &&'a str) -> bool {
66        match self {
67            AttributeDecl::Reference(name) => other.eq(name),
68            _ => false,
69        }
70    }
71}
72
73#[derive(Debug, Clone, PartialEq)]
74pub struct EntityAttribute {
75    pub name: AttributeDecl,
76    pub ty: Type,
77    pub optional: bool,
78}
79
80#[derive(Debug, Clone, PartialEq)]
81pub struct DeriveClause {
82    pub attributes: Vec<DerivedAttribute>,
83}
84
85#[derive(Debug, Clone, PartialEq)]
86pub struct DerivedAttribute {
87    pub attr: AttributeDecl,
88    pub ty: Type,
89    pub expr: Expression,
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub struct InverseClause {
94    pub attributes: Vec<InverseAttribute>,
95}
96
97/// Attribute of an inverse clause parsed by [inverse_attr]
98///
99/// From ISO 10303-11 document,
100///
101/// ```text
102/// ENTITY door;
103///   handle : knob;                -- inverse relationship for this attribute
104///   hinges : SET [1:?] OF hinge;
105/// END_ENTITY;
106///
107/// ENTITY knob;
108/// ...
109/// INVERSE
110///   opens : door FOR handle;
111/// (* ^      ^        ^
112///    |      |        attribute name used in the parent entity
113///    |      The entity which has `SELF` as attribute
114///    name of this inverse relationship *)
115/// END_ENTITY;
116/// ```
117///
118/// This means
119///
120/// > knobs can only exist if they are used in the role of handle in one instance of a door
121///
122#[derive(Debug, Clone, PartialEq)]
123pub struct InverseAttribute {
124    /// Name of this inverse relationship
125    ///
126    /// `opens` in above example
127    pub name: AttributeDecl,
128
129    /// The entity name which has `SELF` as an attribute
130    ///
131    /// `door` in above example
132    pub dest: String,
133
134    /// Used if `SET` or `BAG` for parent entity specification
135    pub dest_aggregation: AggregationOption,
136
137    /// The attribute name used in the parent entity
138    ///
139    /// `handle` in above example
140    pub attribute: String,
141
142    /// Prefix of the attribute, used if the attribute is a sub-attribute of `dest` entity
143    pub attribute_prefix: Option<String>,
144}
145
146#[derive(Debug, Clone, PartialEq)]
147pub enum AggregationOption {
148    Set { bound: Option<Bound> },
149    Bag { bound: Option<Bound> },
150    None,
151}
152
153#[derive(Debug, Clone, PartialEq, Eq)]
154pub enum Constraint {
155    AbstractEntity,
156    AbstractSuperType(Option<SuperTypeExpression>),
157    SuperTypeRule(SuperTypeExpression),
158}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub struct SubTypeDecl {
162    pub entity_references: Vec<String>,
163}
164
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub enum SuperTypeExpression {
167    Reference(String),
168    AndOr { factors: Vec<SuperTypeExpression> },
169    And { terms: Vec<SuperTypeExpression> },
170    OneOf { exprs: Vec<SuperTypeExpression> },
171}
172
173#[derive(Debug, Clone, PartialEq)]
174pub struct SubTypeConstraint {
175    pub name: String,
176    pub entity: String,
177    pub is_abstract: bool,
178    pub total_over: Option<Vec<String>>,
179    pub expr: Option<SuperTypeExpression>,
180}
181
182#[derive(Debug, Clone, PartialEq)]
183pub struct UniqueClause {
184    pub rules: Vec<UniqueRule>,
185}
186
187#[derive(Debug, Clone, PartialEq)]
188pub struct UniqueRule {
189    pub name: Option<String>,
190    pub attributes: Vec<AttributeDecl>,
191}