Skip to main content

sct_ecl/
print.rs

1// SPDX-FileCopyrightText: Cadasto B.V.
2// SPDX-License-Identifier: BUSL-1.1
3
4//! The canonical text of a syntax tree: `Display` for every node, in the
5//! grammar's own spelling, so `parse(print(tree)) == tree`.
6
7use std::fmt::{self, Display, Formatter};
8
9use crate::ast::{
10    Acceptability, AcceptabilitySet, AltIdentifier, Attribute, AttributeSet, AttributeValue,
11    Cardinality, Comparison, ConceptFilter, ConceptReference, ConceptSet, ConstraintOperator,
12    DefinitionStatus, DescriptionFilter, DialectAlias, DialectIdValue, Equality,
13    ExpressionConstraint, FieldValue, FilterConstraint, FocusConcept, HistorySupplement,
14    MemberFilter, MemberOf, NumericValue, Refinement, RefsetFields, Sctid, SubAttributeSet,
15    SubExpressionConstraint, SubRefinement, TimeValue, TypeToken, TypedSearchTerm,
16};
17
18/// Writes `items` separated by `separator`.
19fn join<T: Display>(f: &mut Formatter<'_>, items: &[T], separator: &str) -> fmt::Result {
20    for (i, item) in items.iter().enumerate() {
21        if i > 0 {
22            f.write_str(separator)?;
23        }
24        write!(f, "{item}")?;
25    }
26    Ok(())
27}
28
29/// Writes one item bare and several as `( a b )`.
30fn bare_or_set<T: Display>(f: &mut Formatter<'_>, items: &[T]) -> fmt::Result {
31    match items {
32        [one] => write!(f, "{one}"),
33        many => {
34            f.write_str("(")?;
35            join(f, many, " ")?;
36            f.write_str(")")
37        }
38    }
39}
40
41/// Writes a quoted string.
42fn quoted(f: &mut Formatter<'_>, text: &str) -> fmt::Result {
43    write!(f, "\"{text}\"")
44}
45
46impl Display for Sctid {
47    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
48        write!(f, "{}", self.0)
49    }
50}
51
52impl Display for ConceptReference {
53    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
54        write!(f, "{}", self.id)?;
55        if let Some(term) = &self.term {
56            write!(f, " |{term}|")?;
57        }
58        Ok(())
59    }
60}
61
62impl Display for AltIdentifier {
63    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64        let bare = self
65            .code
66            .chars()
67            .all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '.' | '_'));
68        if bare {
69            write!(f, "{}#{}", self.scheme, self.code)?;
70        } else {
71            write!(f, "\"{}#{}\"", self.scheme, self.code)?;
72        }
73        if let Some(term) = &self.term {
74            write!(f, " |{term}|")?;
75        }
76        Ok(())
77    }
78}
79
80impl Display for FocusConcept {
81    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
82        match self {
83            Self::Reference(reference) => write!(f, "{reference}"),
84            Self::Wildcard => f.write_str("*"),
85            Self::AltIdentifier(alt) => write!(f, "{alt}"),
86            Self::Nested(inner) => write!(f, "( {inner} )"),
87        }
88    }
89}
90
91impl Display for ConstraintOperator {
92    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
93        f.write_str(match self {
94            Self::DescendantOf => "<",
95            Self::DescendantOrSelfOf => "<<",
96            Self::ChildOf => "<!",
97            Self::ChildOrSelfOf => "<<!",
98            Self::AncestorOf => ">",
99            Self::AncestorOrSelfOf => ">>",
100            Self::ParentOf => ">!",
101            Self::ParentOrSelfOf => ">>!",
102            Self::Top => "!!>",
103            Self::Bottom => "!!<",
104        })
105    }
106}
107
108impl Display for MemberOf {
109    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
110        f.write_str("^")?;
111        match &self.fields {
112            None => Ok(()),
113            Some(RefsetFields::Any) => f.write_str(" [*]"),
114            Some(RefsetFields::Names(names)) => {
115                f.write_str(" [")?;
116                join(f, names, ", ")?;
117                f.write_str("]")
118            }
119        }
120    }
121}
122
123impl Display for SubExpressionConstraint {
124    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
125        if let Some(operator) = self.operator {
126            write!(f, "{operator} ")?;
127        }
128        if let Some(member_of) = &self.member_of {
129            write!(f, "{member_of} ")?;
130        }
131        write!(f, "{}", self.focus)?;
132        for filters in &self.member_filters {
133            f.write_str(" {{ M ")?;
134            join(f, filters, ", ")?;
135            f.write_str(" }}")?;
136        }
137        for filter in &self.filters {
138            write!(f, " {filter}")?;
139        }
140        if let Some(history) = &self.history {
141            write!(f, " {history}")?;
142        }
143        Ok(())
144    }
145}
146
147impl Display for FilterConstraint {
148    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
149        match self {
150            Self::Description(filters) => {
151                f.write_str("{{ D ")?;
152                join(f, filters, ", ")?;
153                f.write_str(" }}")
154            }
155            Self::Concept(filters) => {
156                f.write_str("{{ C ")?;
157                join(f, filters, ", ")?;
158                f.write_str(" }}")
159            }
160        }
161    }
162}
163
164impl Display for ExpressionConstraint {
165    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
166        match self {
167            Self::Refined { focus, refinement } => write!(f, "{focus} : {refinement}"),
168            Self::Conjunction(operands) => join(f, operands, " AND "),
169            Self::Disjunction(operands) => join(f, operands, " OR "),
170            Self::Exclusion { left, right } => write!(f, "{left} MINUS {right}"),
171            Self::Dotted { focus, attributes } => {
172                write!(f, "{focus}")?;
173                for attribute in attributes {
174                    write!(f, " . {attribute}")?;
175                }
176                Ok(())
177            }
178            Self::Sub(sub) => write!(f, "{sub}"),
179        }
180    }
181}
182
183impl Display for Refinement {
184    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
185        match self {
186            Self::Single(one) => write!(f, "{one}"),
187            Self::Conjunction(items) => join(f, items, ", "),
188            Self::Disjunction(items) => join(f, items, " OR "),
189        }
190    }
191}
192
193impl Display for SubRefinement {
194    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
195        match self {
196            Self::AttributeSet(set) => write!(f, "{set}"),
197            Self::Group {
198                cardinality,
199                attributes,
200            } => {
201                if let Some(cardinality) = cardinality {
202                    write!(f, "{cardinality} ")?;
203                }
204                write!(f, "{{ {attributes} }}")
205            }
206            Self::Nested(inner) => write!(f, "( {inner} )"),
207        }
208    }
209}
210
211impl Display for AttributeSet {
212    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
213        match self {
214            Self::Single(one) => write!(f, "{one}"),
215            Self::Conjunction(items) => join(f, items, ", "),
216            Self::Disjunction(items) => join(f, items, " OR "),
217        }
218    }
219}
220
221impl Display for SubAttributeSet {
222    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
223        match self {
224            Self::Attribute(attribute) => write!(f, "{attribute}"),
225            Self::Nested(inner) => write!(f, "( {inner} )"),
226        }
227    }
228}
229
230impl Display for Attribute {
231    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
232        if let Some(cardinality) = self.cardinality {
233            write!(f, "{cardinality} ")?;
234        }
235        if self.reverse {
236            f.write_str("R ")?;
237        }
238        write!(f, "{} {}", self.name, self.value)
239    }
240}
241
242impl Display for AttributeValue {
243    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
244        match self {
245            Self::Expression { operator, value } => write!(f, "{operator} {value}"),
246            Self::Numeric { operator, value } => write!(f, "{operator} {value}"),
247            Self::String { operator, terms } => {
248                write!(f, "{operator} ")?;
249                bare_or_set(f, terms)
250            }
251            Self::Boolean { operator, value } => write!(f, "{operator} {value}"),
252        }
253    }
254}
255
256impl Display for Cardinality {
257    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
258        match self.max {
259            Some(max) => write!(f, "[{}..{max}]", self.min),
260            None => write!(f, "[{}..*]", self.min),
261        }
262    }
263}
264
265impl Display for Equality {
266    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
267        f.write_str(match self {
268            Self::Equal => "=",
269            Self::NotEqual => "!=",
270        })
271    }
272}
273
274impl Display for Comparison {
275    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
276        f.write_str(match self {
277            Self::Equal => "=",
278            Self::NotEqual => "!=",
279            Self::Less => "<",
280            Self::LessOrEqual => "<=",
281            Self::Greater => ">",
282            Self::GreaterOrEqual => ">=",
283        })
284    }
285}
286
287impl Display for NumericValue {
288    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
289        write!(f, "#{}", self.0)
290    }
291}
292
293impl Display for TypedSearchTerm {
294    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
295        match self {
296            Self::Match(words) => {
297                f.write_str("\"")?;
298                join(f, words, " ")?;
299                f.write_str("\"")
300            }
301            Self::Wild(pattern) => {
302                f.write_str("wild:")?;
303                quoted(f, pattern)
304            }
305        }
306    }
307}
308
309impl Display for DescriptionFilter {
310    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
311        match self {
312            Self::Term { operator, terms } => {
313                write!(f, "term {operator} ")?;
314                bare_or_set(f, terms)
315            }
316            Self::Language { operator, codes } => {
317                write!(f, "language {operator} ")?;
318                bare_or_set(f, codes)
319            }
320            Self::TypeId { operator, value } => write!(f, "typeId {operator} {value}"),
321            Self::Type { operator, tokens } => {
322                write!(f, "type {operator} ")?;
323                bare_or_set(f, tokens)
324            }
325            Self::DialectId {
326                operator,
327                value,
328                acceptability,
329            } => {
330                write!(f, "dialectId {operator} {value}")?;
331                if let Some(acceptability) = acceptability {
332                    write!(f, " {acceptability}")?;
333                }
334                Ok(())
335            }
336            Self::Dialect {
337                operator,
338                aliases,
339                acceptability,
340            } => {
341                write!(f, "dialect {operator} ")?;
342                match aliases.as_slice() {
343                    [
344                        DialectAlias {
345                            alias,
346                            acceptability: None,
347                        },
348                    ] => f.write_str(alias)?,
349                    many => {
350                        f.write_str("(")?;
351                        join(f, many, " ")?;
352                        f.write_str(")")?;
353                    }
354                }
355                if let Some(acceptability) = acceptability {
356                    write!(f, " {acceptability}")?;
357                }
358                Ok(())
359            }
360            Self::Module { operator, value } => write!(f, "moduleId {operator} {value}"),
361            Self::EffectiveTime { operator, values } => {
362                write!(f, "effectiveTime {operator} ")?;
363                bare_or_set(f, values)
364            }
365            Self::Active { operator, value } => write!(f, "active {operator} {value}"),
366            Self::Id { operator, ids } => {
367                write!(f, "id {operator} ")?;
368                bare_or_set(f, ids)
369            }
370        }
371    }
372}
373
374impl Display for ConceptSet {
375    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
376        match self {
377            Self::Expression(sub) => write!(f, "{sub}"),
378            Self::Set(references) => {
379                f.write_str("(")?;
380                join(f, references, " ")?;
381                f.write_str(")")
382            }
383        }
384    }
385}
386
387impl Display for TypeToken {
388    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
389        f.write_str(match self {
390            Self::Synonym => "syn",
391            Self::FullySpecifiedName => "fsn",
392            Self::Definition => "def",
393        })
394    }
395}
396
397impl Display for DialectIdValue {
398    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
399        match self {
400            Self::Expression(sub) => write!(f, "{sub}"),
401            Self::Set(items) => {
402                f.write_str("(")?;
403                for (i, (reference, acceptability)) in items.iter().enumerate() {
404                    if i > 0 {
405                        f.write_str(" ")?;
406                    }
407                    write!(f, "{reference}")?;
408                    if let Some(acceptability) = acceptability {
409                        write!(f, " {acceptability}")?;
410                    }
411                }
412                f.write_str(")")
413            }
414        }
415    }
416}
417
418impl Display for DialectAlias {
419    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
420        f.write_str(&self.alias)?;
421        if let Some(acceptability) = &self.acceptability {
422            write!(f, " {acceptability}")?;
423        }
424        Ok(())
425    }
426}
427
428impl Display for AcceptabilitySet {
429    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
430        f.write_str("(")?;
431        match self {
432            Self::Concepts(references) => join(f, references, " ")?,
433            Self::Tokens(tokens) => join(f, tokens, " ")?,
434        }
435        f.write_str(")")
436    }
437}
438
439impl Display for Acceptability {
440    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
441        f.write_str(match self {
442            Self::Acceptable => "accept",
443            Self::Preferred => "prefer",
444        })
445    }
446}
447
448impl Display for TimeValue {
449    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
450        quoted(f, &self.0)
451    }
452}
453
454impl Display for ConceptFilter {
455    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
456        match self {
457            Self::DefinitionStatusId { operator, value } => {
458                write!(f, "definitionStatusId {operator} {value}")
459            }
460            Self::DefinitionStatus { operator, tokens } => {
461                write!(f, "definitionStatus {operator} ")?;
462                bare_or_set(f, tokens)
463            }
464            Self::Module { operator, value } => write!(f, "moduleId {operator} {value}"),
465            Self::EffectiveTime { operator, values } => {
466                write!(f, "effectiveTime {operator} ")?;
467                bare_or_set(f, values)
468            }
469            Self::Active { operator, value } => write!(f, "active {operator} {value}"),
470        }
471    }
472}
473
474impl Display for DefinitionStatus {
475    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
476        f.write_str(match self {
477            Self::Primitive => "primitive",
478            Self::Defined => "defined",
479        })
480    }
481}
482
483impl Display for MemberFilter {
484    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
485        match self {
486            Self::Module { operator, value } => write!(f, "moduleId {operator} {value}"),
487            Self::EffectiveTime { operator, values } => {
488                write!(f, "effectiveTime {operator} ")?;
489                bare_or_set(f, values)
490            }
491            Self::Active { operator, value } => write!(f, "active {operator} {value}"),
492            Self::Field { name, value } => write!(f, "{name} {value}"),
493        }
494    }
495}
496
497impl Display for FieldValue {
498    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
499        match self {
500            Self::Expression { operator, value } => write!(f, "{operator} {value}"),
501            Self::Numeric { operator, value } => write!(f, "{operator} {value}"),
502            Self::String { operator, terms } => {
503                write!(f, "{operator} ")?;
504                bare_or_set(f, terms)
505            }
506            Self::Boolean { operator, value } => write!(f, "{operator} {value}"),
507            Self::Time { operator, values } => {
508                write!(f, "{operator} ")?;
509                bare_or_set(f, values)
510            }
511        }
512    }
513}
514
515impl Display for HistorySupplement {
516    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
517        match self {
518            Self::Default => f.write_str("{{ + HISTORY }}"),
519            Self::Minimum => f.write_str("{{ + HISTORY-MIN }}"),
520            Self::Moderate => f.write_str("{{ + HISTORY-MOD }}"),
521            Self::Maximum => f.write_str("{{ + HISTORY-MAX }}"),
522            Self::Subset(inner) => write!(f, "{{{{ + HISTORY ( {inner} ) }}}}"),
523        }
524    }
525}