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