sct_ecl/ast.rs
1// SPDX-FileCopyrightText: Cadasto B.V.
2// SPDX-License-Identifier: BUSL-1.1
3
4//! The syntax tree of an expression constraint, one type per grammar rule
5//! that carries meaning (`ECL.g4`; the rules that only spell a keyword or a
6//! character class are folded into their parents).
7
8/// A SNOMED CT identifier as written in an expression (`sctid`: 6 to 18
9/// digits, the first not zero).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Sctid(pub u64);
12
13/// `eclconceptreference`: an identifier with its optional term.
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct ConceptReference {
16 /// The identifier.
17 pub id: Sctid,
18 /// The term between pipes, trimmed.
19 pub term: Option<String>,
20}
21
22/// `altidentifier`: a code from another scheme (`LOINC#54486-6`).
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct AltIdentifier {
25 /// The scheme alias before the `#`.
26 pub scheme: String,
27 /// The code after the `#`.
28 pub code: String,
29 /// The term between pipes, trimmed.
30 pub term: Option<String>,
31}
32
33/// `eclfocusconcept`, or a parenthesized nested constraint.
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub enum FocusConcept {
36 /// A concept reference.
37 Reference(ConceptReference),
38 /// `*`, any concept.
39 Wildcard,
40 /// An alternate identifier.
41 AltIdentifier(AltIdentifier),
42 /// `( expressionconstraint )`.
43 Nested(Box<ExpressionConstraint>),
44}
45
46/// `constraintoperator`.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48pub enum ConstraintOperator {
49 /// `<`
50 DescendantOf,
51 /// `<<`
52 DescendantOrSelfOf,
53 /// `<!`
54 ChildOf,
55 /// `<<!`
56 ChildOrSelfOf,
57 /// `>`
58 AncestorOf,
59 /// `>>`
60 AncestorOrSelfOf,
61 /// `>!`
62 ParentOf,
63 /// `>>!`
64 ParentOrSelfOf,
65 /// `!!>`
66 Top,
67 /// `!!<`
68 Bottom,
69}
70
71/// The reference set fields a `memberof` names (`^ [field, field]`).
72#[derive(Debug, Clone, PartialEq, Eq, Hash)]
73pub enum RefsetFields {
74 /// `[*]`.
75 Any,
76 /// `[name, name]`.
77 Names(Vec<String>),
78}
79
80/// `memberof`: `^`, with its optional field selection.
81#[derive(Debug, Clone, PartialEq, Eq, Hash)]
82pub struct MemberOf {
83 /// The fields between brackets, when given.
84 pub fields: Option<RefsetFields>,
85}
86
87/// `refsetOperator`: `memberOf` or `refsetContainingAny`.
88#[derive(Debug, Clone, PartialEq, Eq, Hash)]
89pub enum RefsetOperator {
90 /// `^`: the members of the reference sets the focus names.
91 MemberOf(MemberOf),
92 /// `^R`: the reference sets with a member the focus names.
93 ContainingAny,
94}
95
96/// `subexpressionconstraint`.
97#[derive(Debug, Clone, PartialEq, Eq, Hash)]
98pub struct SubExpressionConstraint {
99 /// The constraint operator before the focus.
100 pub operator: Option<ConstraintOperator>,
101 /// The `^` or `^R` before the focus.
102 pub refset_operator: Option<RefsetOperator>,
103 /// The focus concept or nested constraint.
104 pub focus: FocusConcept,
105 /// `memberfilterconstraint`s, one list per `{{ M ... }}`.
106 pub member_filters: Vec<Vec<MemberFilter>>,
107 /// The description and concept filter constraints, in order.
108 pub filters: Vec<FilterConstraint>,
109 /// `historysupplement`.
110 pub history: Option<HistorySupplement>,
111}
112
113/// `descriptionfilterconstraint` or `conceptfilterconstraint`.
114#[derive(Debug, Clone, PartialEq, Eq, Hash)]
115pub enum FilterConstraint {
116 /// `{{ D ... }}`.
117 Description(Vec<DescriptionFilter>),
118 /// `{{ C ... }}`.
119 Concept(Vec<ConceptFilter>),
120}
121
122/// `expressionconstraint`.
123#[derive(Debug, Clone, PartialEq, Eq, Hash)]
124pub enum ExpressionConstraint {
125 /// `refinedexpressionconstraint`: a focus with `:` and a refinement.
126 Refined {
127 /// The constraint refined.
128 focus: SubExpressionConstraint,
129 /// The refinement.
130 refinement: Box<Refinement>,
131 },
132 /// `conjunctionexpressionconstraint`, two or more operands.
133 Conjunction(Vec<SubExpressionConstraint>),
134 /// `disjunctionexpressionconstraint`, two or more operands.
135 Disjunction(Vec<SubExpressionConstraint>),
136 /// `exclusionexpressionconstraint`.
137 Exclusion {
138 /// The set kept.
139 left: SubExpressionConstraint,
140 /// The set removed.
141 right: SubExpressionConstraint,
142 },
143 /// `dottedexpressionconstraint`: a focus followed by `. attribute` steps.
144 Dotted {
145 /// The constraint the walk starts from.
146 focus: SubExpressionConstraint,
147 /// The attribute names walked, in order.
148 attributes: Vec<SubExpressionConstraint>,
149 },
150 /// A bare `subexpressionconstraint`.
151 Sub(SubExpressionConstraint),
152}
153
154/// `eclrefinement`.
155#[derive(Debug, Clone, PartialEq, Eq, Hash)]
156pub enum Refinement {
157 /// One sub-refinement.
158 Single(Box<SubRefinement>),
159 /// Sub-refinements joined by `AND` or `,`, two or more.
160 Conjunction(Vec<SubRefinement>),
161 /// Sub-refinements joined by `OR`, two or more.
162 Disjunction(Vec<SubRefinement>),
163}
164
165/// `subrefinement`.
166#[derive(Debug, Clone, PartialEq, Eq, Hash)]
167pub enum SubRefinement {
168 /// An attribute set.
169 AttributeSet(AttributeSet),
170 /// `eclattributegroup`: `[c] { attributes }`.
171 Group {
172 /// The group cardinality.
173 cardinality: Option<Cardinality>,
174 /// The attributes in the group.
175 attributes: AttributeSet,
176 },
177 /// `( eclrefinement )`.
178 Nested(Box<Refinement>),
179}
180
181/// `eclattributeset`.
182#[derive(Debug, Clone, PartialEq, Eq, Hash)]
183pub enum AttributeSet {
184 /// One sub-attribute set.
185 Single(Box<SubAttributeSet>),
186 /// Joined by `AND` or `,`, two or more.
187 Conjunction(Vec<SubAttributeSet>),
188 /// Joined by `OR`, two or more.
189 Disjunction(Vec<SubAttributeSet>),
190}
191
192/// `subattributeset`.
193#[derive(Debug, Clone, PartialEq, Eq, Hash)]
194pub enum SubAttributeSet {
195 /// An attribute.
196 Attribute(Box<Attribute>),
197 /// `( eclattributeset )`.
198 Nested(Box<AttributeSet>),
199}
200
201/// `eclattribute`.
202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
203pub struct Attribute {
204 /// `[min..max]` before the name.
205 pub cardinality: Option<Cardinality>,
206 /// The reverse flag `R`.
207 pub reverse: bool,
208 /// `eclattributename`, a sub-expression constraint.
209 pub name: SubExpressionConstraint,
210 /// The comparison and value.
211 pub value: AttributeValue,
212}
213
214/// The comparison and value of an attribute or a member field.
215#[derive(Debug, Clone, PartialEq, Eq, Hash)]
216pub enum AttributeValue {
217 /// `= sub` or `!= sub`.
218 Expression {
219 /// The operator.
220 operator: Equality,
221 /// The value constraint.
222 value: SubExpressionConstraint,
223 },
224 /// `op #number`.
225 Numeric {
226 /// The operator.
227 operator: Comparison,
228 /// The number.
229 value: NumericValue,
230 },
231 /// `= "string"` or `= ("string" "string")`: `concretestring` or
232 /// `concretestringset`.
233 String {
234 /// The operator.
235 operator: Equality,
236 /// The strings; one prints bare, more print as a set.
237 values: Vec<ConcreteString>,
238 },
239 /// `= true` or `= false`.
240 Boolean {
241 /// The operator.
242 operator: Equality,
243 /// The value.
244 value: bool,
245 },
246}
247
248/// `cardinality`: `min..max`, `max` absent for `*`.
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
250pub struct Cardinality {
251 /// The minimum.
252 pub min: u32,
253 /// The maximum, `None` for `*`.
254 pub max: Option<u32>,
255}
256
257/// `expressioncomparisonoperator`, `stringcomparisonoperator`,
258/// `booleancomparisonoperator`, and `idcomparisonoperator`.
259#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
260pub enum Equality {
261 /// `=`
262 Equal,
263 /// `!=`
264 NotEqual,
265}
266
267/// `numericcomparisonoperator` and `timecomparisonoperator`.
268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
269pub enum Comparison {
270 /// `=`
271 Equal,
272 /// `!=`
273 NotEqual,
274 /// `<`
275 Less,
276 /// `<=`
277 LessOrEqual,
278 /// `>`
279 Greater,
280 /// `>=`
281 GreaterOrEqual,
282}
283
284/// `numericvalue`: the literal after `#`, as written (an optional sign,
285/// digits, an optional fraction).
286#[derive(Debug, Clone, PartialEq, Eq, Hash)]
287pub struct NumericValue(pub String);
288
289/// `concretestring`: the string between the quotes with its escapes
290/// (`\"`, `\\`, `\*`) decoded, compared exactly.
291#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292pub struct ConcreteString(pub String);
293
294/// `activevalue`.
295#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
296pub enum ActiveValue {
297 /// `1` or `true`.
298 Active,
299 /// `0` or `false`.
300 Inactive,
301 /// `*`: either status.
302 Any,
303}
304
305/// `typedsearchterm`.
306#[derive(Debug, Clone, PartialEq, Eq, Hash)]
307pub enum TypedSearchTerm {
308 /// `"word word"` or `match:"..."`: every word must match as a prefix.
309 Match(Vec<String>),
310 /// `wild:"..."`: a pattern with `*` wildcards.
311 Wild(String),
312}
313
314/// `descriptionfilter`.
315#[derive(Debug, Clone, PartialEq, Eq, Hash)]
316pub enum DescriptionFilter {
317 /// `term op terms`.
318 Term {
319 /// The operator.
320 operator: Equality,
321 /// The search terms.
322 terms: Vec<TypedSearchTerm>,
323 },
324 /// `language op codes`.
325 Language {
326 /// The operator.
327 operator: Equality,
328 /// Two-letter language codes.
329 codes: Vec<String>,
330 },
331 /// `typeId op concepts`.
332 TypeId {
333 /// The operator.
334 operator: Equality,
335 /// The description type concepts.
336 value: ConceptSet,
337 },
338 /// `type op tokens`.
339 Type {
340 /// The operator.
341 operator: Equality,
342 /// The description type tokens.
343 tokens: Vec<TypeToken>,
344 },
345 /// `dialectId op value [acceptability]`.
346 DialectId {
347 /// The operator.
348 operator: Equality,
349 /// The language reference sets.
350 value: DialectIdValue,
351 /// The acceptability that applies to every dialect named.
352 acceptability: Option<AcceptabilitySet>,
353 },
354 /// `dialect op aliases [acceptability]`.
355 Dialect {
356 /// The operator.
357 operator: Equality,
358 /// The dialect aliases with their own acceptability.
359 aliases: Vec<DialectAlias>,
360 /// The acceptability that applies to every dialect named.
361 acceptability: Option<AcceptabilitySet>,
362 },
363 /// `moduleId op concepts`.
364 Module {
365 /// The operator.
366 operator: Equality,
367 /// The modules.
368 value: ConceptSet,
369 },
370 /// `effectiveTime op times`.
371 EffectiveTime {
372 /// The operator.
373 operator: Comparison,
374 /// The times.
375 values: Vec<TimeValue>,
376 },
377 /// `active op value`.
378 Active {
379 /// The operator.
380 operator: Equality,
381 /// The value.
382 value: ActiveValue,
383 },
384 /// `id op ids`.
385 Id {
386 /// The operator.
387 operator: Equality,
388 /// The description identifiers.
389 ids: Vec<Sctid>,
390 },
391}
392
393/// A sub-expression constraint or a set of two or more concept references
394/// (`subexpressionconstraint | eclconceptreferenceset`).
395#[derive(Debug, Clone, PartialEq, Eq, Hash)]
396pub enum ConceptSet {
397 /// A constraint.
398 Expression(SubExpressionConstraint),
399 /// `( ref ref ... )`, two or more.
400 Set(Vec<ConceptReference>),
401}
402
403/// `typetoken`.
404#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
405pub enum TypeToken {
406 /// `syn`
407 Synonym,
408 /// `fsn`
409 FullySpecifiedName,
410 /// `def`
411 Definition,
412}
413
414/// The value of a `dialectidfilter`.
415#[derive(Debug, Clone, PartialEq, Eq, Hash)]
416pub enum DialectIdValue {
417 /// A constraint.
418 Expression(SubExpressionConstraint),
419 /// `( ref [acceptability] ... )`, one or more.
420 Set(Vec<(ConceptReference, Option<AcceptabilitySet>)>),
421}
422
423/// One alias of a `dialectaliasfilter`.
424#[derive(Debug, Clone, PartialEq, Eq, Hash)]
425pub struct DialectAlias {
426 /// The alias (`en-gb`).
427 pub alias: String,
428 /// The acceptability for this alias alone.
429 pub acceptability: Option<AcceptabilitySet>,
430}
431
432/// `acceptabilityset`.
433#[derive(Debug, Clone, PartialEq, Eq, Hash)]
434pub enum AcceptabilitySet {
435 /// Acceptability concepts, one or more.
436 Concepts(Vec<ConceptReference>),
437 /// `accept` and `prefer` tokens, one or more.
438 Tokens(Vec<Acceptability>),
439}
440
441/// `acceptabilitytoken`.
442#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
443pub enum Acceptability {
444 /// `accept`
445 Acceptable,
446 /// `prefer`
447 Preferred,
448}
449
450/// `timevalue`: `YYYYMMDD` or empty.
451#[derive(Debug, Clone, PartialEq, Eq, Hash)]
452pub struct TimeValue(pub String);
453
454/// `conceptfilter`.
455#[derive(Debug, Clone, PartialEq, Eq, Hash)]
456pub enum ConceptFilter {
457 /// `definitionStatusId op concepts`.
458 DefinitionStatusId {
459 /// The operator.
460 operator: Equality,
461 /// The definition status concepts.
462 value: ConceptSet,
463 },
464 /// `definitionStatus op tokens`.
465 DefinitionStatus {
466 /// The operator.
467 operator: Equality,
468 /// The tokens.
469 tokens: Vec<DefinitionStatus>,
470 },
471 /// `moduleId op concepts`.
472 Module {
473 /// The operator.
474 operator: Equality,
475 /// The modules.
476 value: ConceptSet,
477 },
478 /// `effectiveTime op times`.
479 EffectiveTime {
480 /// The operator.
481 operator: Comparison,
482 /// The times.
483 values: Vec<TimeValue>,
484 },
485 /// `active op value`.
486 Active {
487 /// The operator.
488 operator: Equality,
489 /// The value.
490 value: ActiveValue,
491 },
492}
493
494/// `definitionstatustoken`.
495#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
496pub enum DefinitionStatus {
497 /// `primitive`
498 Primitive,
499 /// `defined`
500 Defined,
501}
502
503/// `memberfilter`.
504#[derive(Debug, Clone, PartialEq, Eq, Hash)]
505pub enum MemberFilter {
506 /// `moduleId op concepts`.
507 Module {
508 /// The operator.
509 operator: Equality,
510 /// The modules.
511 value: ConceptSet,
512 },
513 /// `effectiveTime op times`.
514 EffectiveTime {
515 /// The operator.
516 operator: Comparison,
517 /// The times.
518 values: Vec<TimeValue>,
519 },
520 /// `active op value`.
521 Active {
522 /// The operator.
523 operator: Equality,
524 /// The value.
525 value: ActiveValue,
526 },
527 /// `memberfieldfilter`: a reference set field compared to a value.
528 Field {
529 /// The field name.
530 name: String,
531 /// The comparison.
532 value: FieldValue,
533 },
534}
535
536/// The comparison of a `memberfieldfilter`.
537#[derive(Debug, Clone, PartialEq, Eq, Hash)]
538pub enum FieldValue {
539 /// `= sub` or `!= sub`.
540 Expression {
541 /// The operator.
542 operator: Equality,
543 /// The value constraint.
544 value: SubExpressionConstraint,
545 },
546 /// `op #number`.
547 Numeric {
548 /// The operator.
549 operator: Comparison,
550 /// The number.
551 value: NumericValue,
552 },
553 /// `= "string"` or a set.
554 String {
555 /// The operator.
556 operator: Equality,
557 /// The search terms.
558 terms: Vec<TypedSearchTerm>,
559 },
560 /// `= true` or `= false`.
561 Boolean {
562 /// The operator.
563 operator: Equality,
564 /// The value.
565 value: bool,
566 },
567 /// `< "time"` and the other ordering operators (`=` and `!=` with a
568 /// quoted value are string comparisons, the grammar's first match).
569 Time {
570 /// The operator: `Less`, `LessOrEqual`, `Greater`, or `GreaterOrEqual`.
571 operator: Comparison,
572 /// The times.
573 values: Vec<TimeValue>,
574 },
575}
576
577/// `historysupplement`.
578#[derive(Debug, Clone, PartialEq, Eq, Hash)]
579pub enum HistorySupplement {
580 /// `{{ + HISTORY }}`, the default profile.
581 Default,
582 /// `{{ + HISTORY-MIN }}`.
583 Minimum,
584 /// `{{ + HISTORY-MOD }}`.
585 Moderate,
586 /// `{{ + HISTORY-MAX }}`.
587 Maximum,
588 /// `{{ + HISTORY ( constraint ) }}`: the association reference sets.
589 Subset(Box<ExpressionConstraint>),
590}