Skip to main content

meta_language/grammar/
feature.rs

1//! The grammar feature union forms (`docs/grammar/feature-union.md`).
2//!
3//! One table describes every expression kind, every operation of the scanner
4//! and action language and every grammar declaration the feature union adds,
5//! and the native listing, links and JSON codecs read and write them from
6//! that table, so the serializations stay in step with each other and with
7//! `js/src/grammar-feature-forms.js`.
8
9use std::collections::BTreeSet;
10
11use super::{CharClassItem, GrammarExpr};
12
13/// The type of one field of a feature form or an operation.
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum FieldType {
16    /// One word out of a fixed list.
17    Choice(&'static [&'static str]),
18    /// A signed integer of at most 15 digits.
19    Integer,
20    /// A name: a rule, mode, token, stack, variable, field or attribute.
21    Name,
22    /// A text value.
23    Text,
24    /// One grammar expression.
25    Expression,
26    /// The remaining grammar expressions.
27    Expressions,
28    /// One condition operation.
29    Condition,
30    /// One value operation.
31    Value,
32    /// The remaining condition operations.
33    Conditions,
34    /// A statement list written as `WORD(...)`; the flag makes it optional.
35    Block(&'static str, bool),
36}
37
38/// The fields of one form, as `(key, type)` pairs in listing order.
39pub type FormFields = &'static [(&'static str, FieldType)];
40
41/// The expression kinds the feature union adds, with their fields in listing order.
42pub const FEATURE_EXPRESSION_FORMS: &[(&str, FormFields)] = &[
43    (
44        "precedence",
45        &[
46            ("level", FieldType::Integer),
47            (
48                "associativity",
49                FieldType::Choice(&["left", "right", "none"]),
50            ),
51            ("item", FieldType::Expression),
52        ],
53    ),
54    (
55        "namedPrecedence",
56        &[
57            ("name", FieldType::Name),
58            (
59                "associativity",
60                FieldType::Choice(&["left", "right", "none"]),
61            ),
62            ("item", FieldType::Expression),
63        ],
64    ),
65    (
66        "dynamicPrecedence",
67        &[
68            ("level", FieldType::Integer),
69            ("item", FieldType::Expression),
70        ],
71    ),
72    (
73        "lexicalPrecedence",
74        &[
75            ("level", FieldType::Integer),
76            ("item", FieldType::Expression),
77        ],
78    ),
79    ("longest", &[("items", FieldType::Expressions)]),
80    ("token", &[("item", FieldType::Expression)]),
81    ("immediateToken", &[("item", FieldType::Expression)]),
82    (
83        "alias",
84        &[("name", FieldType::Name), ("item", FieldType::Expression)],
85    ),
86    ("parameter", &[("name", FieldType::Name)]),
87    (
88        "predicate",
89        &[
90            ("item", FieldType::Expression),
91            ("condition", FieldType::Condition),
92        ],
93    ),
94    (
95        "recover",
96        &[
97            ("item", FieldType::Expression),
98            ("synchronize", FieldType::Expression),
99        ],
100    ),
101    ("missing", &[("item", FieldType::Expression)]),
102    (
103        "embed",
104        &[
105            ("language", FieldType::Name),
106            ("item", FieldType::Expression),
107        ],
108    ),
109    (
110        "expand",
111        &[
112            ("name", FieldType::Name),
113            ("arguments", FieldType::Expressions),
114        ],
115    ),
116];
117
118/// Whether an operation is a statement, a condition or a value.
119#[derive(Clone, Copy, Debug, PartialEq, Eq)]
120pub enum OperationCategory {
121    /// An operation run for its effect.
122    Statement,
123    /// An operation that holds or does not.
124    Condition,
125    /// An operation that computes an integer or a text.
126    Value,
127}
128
129impl OperationCategory {
130    /// The category's word in error messages.
131    #[must_use]
132    pub const fn as_str(self) -> &'static str {
133        match self {
134            Self::Statement => "statement",
135            Self::Condition => "condition",
136            Self::Value => "value",
137        }
138    }
139}
140
141const TWO_VALUES: FormFields = &[("left", FieldType::Value), ("right", FieldType::Value)];
142const STATEMENT: OperationCategory = OperationCategory::Statement;
143const CONDITION: OperationCategory = OperationCategory::Condition;
144const VALUE: OperationCategory = OperationCategory::Value;
145
146/// The operation language of external scanners, semantic actions and
147/// predicates, with each operation's category and fields in listing order.
148pub const OPERATION_FORMS: &[(&str, OperationCategory, FormFields)] = &[
149    ("advance", STATEMENT, &[]),
150    ("consume", STATEMENT, &[("item", FieldType::Expression)]),
151    ("skip", STATEMENT, &[("item", FieldType::Expression)]),
152    ("mark", STATEMENT, &[]),
153    ("emit", STATEMENT, &[("token", FieldType::Name)]),
154    ("fail", STATEMENT, &[]),
155    (
156        "if",
157        STATEMENT,
158        &[
159            ("condition", FieldType::Condition),
160            ("consequent", FieldType::Block("then", false)),
161            ("alternative", FieldType::Block("else", true)),
162        ],
163    ),
164    (
165        "while",
166        STATEMENT,
167        &[
168            ("condition", FieldType::Condition),
169            ("body", FieldType::Block("do", false)),
170        ],
171    ),
172    (
173        "push",
174        STATEMENT,
175        &[("stack", FieldType::Name), ("value", FieldType::Value)],
176    ),
177    ("pop", STATEMENT, &[("stack", FieldType::Name)]),
178    (
179        "set",
180        STATEMENT,
181        &[("variable", FieldType::Name), ("value", FieldType::Value)],
182    ),
183    ("pushMode", STATEMENT, &[("mode", FieldType::Name)]),
184    ("popMode", STATEMENT, &[]),
185    ("setMode", STATEMENT, &[("mode", FieldType::Name)]),
186    (
187        "setAttribute",
188        STATEMENT,
189        &[("attribute", FieldType::Name), ("value", FieldType::Value)],
190    ),
191    ("buildNode", STATEMENT, &[("kind", FieldType::Name)]),
192    ("valid", CONDITION, &[("token", FieldType::Name)]),
193    ("expected", CONDITION, &[("item", FieldType::Expression)]),
194    ("next", CONDITION, &[("item", FieldType::Expression)]),
195    ("atEnd", CONDITION, &[]),
196    ("equal", CONDITION, TWO_VALUES),
197    ("less", CONDITION, TWO_VALUES),
198    ("greater", CONDITION, TWO_VALUES),
199    ("all", CONDITION, &[("conditions", FieldType::Conditions)]),
200    ("some", CONDITION, &[("conditions", FieldType::Conditions)]),
201    ("not", CONDITION, &[("condition", FieldType::Condition)]),
202    ("integer", VALUE, &[("value", FieldType::Integer)]),
203    ("text", VALUE, &[("value", FieldType::Text)]),
204    ("variable", VALUE, &[("name", FieldType::Name)]),
205    ("top", VALUE, &[("stack", FieldType::Name)]),
206    ("depth", VALUE, &[("stack", FieldType::Name)]),
207    ("column", VALUE, &[]),
208    ("matched", VALUE, &[]),
209    ("mode", VALUE, &[]),
210    (
211        "attribute",
212        VALUE,
213        &[("field", FieldType::Name), ("attribute", FieldType::Name)],
214    ),
215    (
216        "sumOf",
217        VALUE,
218        &[("field", FieldType::Name), ("attribute", FieldType::Name)],
219    ),
220    ("fieldText", VALUE, &[("field", FieldType::Name)]),
221    ("length", VALUE, &[("value", FieldType::Value)]),
222    ("number", VALUE, &[("value", FieldType::Value)]),
223    ("add", VALUE, TWO_VALUES),
224    ("subtract", VALUE, TWO_VALUES),
225    ("multiply", VALUE, TWO_VALUES),
226];
227
228/// The ways a grammar may match: generalized (every alternative), PEG (first
229/// and greedy) or longest (generalized, ties going to the longer token).
230pub const MATCHING_MODES: &[&str] = &["generalized", "peg", "longest"];
231
232/// The steps that settle two parses of one text that end alike, as a
233/// grammar's `(settling STEP ...)` declares them.
234///
235/// In order (the lower repair cost always decides first): `tokens`, the tokens a lexer prefers (higher
236/// lexical precedence, longer, a literal over a pattern, earlier), with the
237/// lexing that goes with it (keywords, separators, immediate tokens);
238/// `precedence`, the shift or reduction an LR parser keeps by precedence and
239/// associativity, forking where a declared conflict asks; `dynamic`, the
240/// higher dynamic precedence. The last step settles a tie: `first` keeps the
241/// parse reached first, `ambiguity` keeps it and reports the ambiguity.
242pub const SETTLING_STEPS: &[&str] = &["tokens", "precedence", "dynamic", "first", "ambiguity"];
243
244/// The settling of a grammar that declares none, by its matching.
245#[must_use]
246pub fn default_settling(matching: &str) -> &'static [&'static str] {
247    match matching {
248        "peg" => &["first"],
249        "longest" => &["tokens", "precedence", "dynamic", "ambiguity"],
250        _ => &["dynamic", "ambiguity"],
251    }
252}
253
254/// Why `steps` is no settling, or `None`: every step is known and given
255/// once, and exactly the last one settles a tie.
256#[must_use]
257pub fn settling_problem<S: AsRef<str>>(steps: &[S]) -> Option<String> {
258    if steps.is_empty() {
259        return Some("the settling names no step".to_owned());
260    }
261    for (index, step) in steps.iter().enumerate() {
262        let step = step.as_ref();
263        if !SETTLING_STEPS.contains(&step) {
264            return Some(format!("unknown settling step {step}"));
265        }
266        if steps.iter().position(|other| other.as_ref() == step) != Some(index) {
267            return Some(format!("the settling step {step} is given twice"));
268        }
269        let tie = step == "first" || step == "ambiguity";
270        if tie != (index == steps.len() - 1) {
271            return Some("the settling ends with exactly one of first and ambiguity".to_owned());
272        }
273    }
274    None
275}
276
277/// The longest integer a form may spell, in decimal digits.
278pub const MAX_INTEGER_DIGITS: usize = 15;
279
280/// The fields of the feature expression form `head`, when it is one.
281#[must_use]
282pub fn feature_expression_fields(head: &str) -> Option<FormFields> {
283    FEATURE_EXPRESSION_FORMS
284        .iter()
285        .find(|(name, _)| *name == head)
286        .map(|(_, fields)| *fields)
287}
288
289/// The category and fields of the operation `head`, when it is one.
290#[must_use]
291pub fn operation_form(head: &str) -> Option<(OperationCategory, FormFields)> {
292    OPERATION_FORMS
293        .iter()
294        .find(|(name, _, _)| *name == head)
295        .map(|(_, category, fields)| (*category, *fields))
296}
297
298/// Checks the text of an integer field: an optional `-` and at most 15 digits.
299///
300/// # Errors
301///
302/// Returns the detail of the failure.
303pub fn check_integer(text: &str) -> Result<i64, String> {
304    let digits = text.strip_prefix('-').unwrap_or(text);
305    if digits.is_empty() || !digits.bytes().all(|byte| byte.is_ascii_digit()) {
306        return Err(format!("expected an integer, not {text}"));
307    }
308    if digits.len() > MAX_INTEGER_DIGITS {
309        return Err(format!("integer {text} is too large"));
310    }
311    text.parse()
312        .map_err(|_| format!("expected an integer, not {text}"))
313}
314
315/// The value of one field of a feature form or an operation.
316#[derive(Clone, Debug, PartialEq, Eq)]
317pub enum FieldValue {
318    /// One word of a [`FieldType::Choice`].
319    Word(String),
320    /// An integer.
321    Integer(i64),
322    /// A name.
323    Name(String),
324    /// A text.
325    Text(String),
326    /// One expression.
327    Expression(GrammarExpr),
328    /// A list of expressions.
329    Expressions(Vec<GrammarExpr>),
330    /// One condition or value.
331    Operation(FeatureForm),
332    /// A list of conditions.
333    Operations(Vec<FeatureForm>),
334    /// A statement block; `None` for an absent optional block.
335    Block(Option<Vec<FeatureForm>>),
336}
337
338/// One feature expression form or one operation: a head word and its field
339/// values, in the order of [`FEATURE_EXPRESSION_FORMS`] or [`OPERATION_FORMS`].
340#[derive(Clone, Debug, PartialEq, Eq)]
341pub struct FeatureForm {
342    /// The form's head word, such as `precedence` or `pushMode`.
343    pub head: String,
344    /// The field values in table order.
345    pub fields: Vec<FieldValue>,
346}
347
348/// One operation of the scanner and action language.
349pub type Operation = FeatureForm;
350
351impl FeatureForm {
352    /// Builds a form from its head and field values.
353    #[must_use]
354    pub fn new(head: impl Into<String>, fields: Vec<FieldValue>) -> Self {
355        Self {
356            head: head.into(),
357            fields,
358        }
359    }
360
361    /// The table fields of this form, as an expression form or an operation.
362    #[must_use]
363    pub fn spec(&self) -> FormFields {
364        feature_expression_fields(&self.head)
365            .or_else(|| operation_form(&self.head).map(|(_, fields)| fields))
366            .unwrap_or(&[])
367    }
368
369    /// The value of the field `key`.
370    #[must_use]
371    pub fn field(&self, key: &str) -> Option<&FieldValue> {
372        let index = self.spec().iter().position(|(name, _)| *name == key)?;
373        self.fields.get(index)
374    }
375
376    /// The expression of the field `key`.
377    #[must_use]
378    pub fn expression(&self, key: &str) -> Option<&GrammarExpr> {
379        match self.field(key)? {
380            FieldValue::Expression(expr) => Some(expr),
381            _ => None,
382        }
383    }
384
385    /// The expression list of the field `key`.
386    #[must_use]
387    pub fn expressions(&self, key: &str) -> &[GrammarExpr] {
388        match self.field(key) {
389            Some(FieldValue::Expressions(items)) => items,
390            _ => &[],
391        }
392    }
393
394    /// The word, name or text of the field `key`.
395    #[must_use]
396    pub fn text(&self, key: &str) -> Option<&str> {
397        match self.field(key)? {
398            FieldValue::Word(value) | FieldValue::Name(value) | FieldValue::Text(value) => {
399                Some(value)
400            }
401            _ => None,
402        }
403    }
404
405    /// The integer of the field `key`.
406    #[must_use]
407    pub fn integer(&self, key: &str) -> Option<i64> {
408        match self.field(key)? {
409            FieldValue::Integer(value) => Some(*value),
410            _ => None,
411        }
412    }
413
414    /// The single operation of the field `key`.
415    #[must_use]
416    pub fn operation(&self, key: &str) -> Option<&Self> {
417        match self.field(key)? {
418            FieldValue::Operation(operation) => Some(operation),
419            _ => None,
420        }
421    }
422
423    /// The operation list or block of the field `key`; `None` for an absent block.
424    #[must_use]
425    pub fn operations(&self, key: &str) -> Option<&[Self]> {
426        match self.field(key)? {
427            FieldValue::Operations(items) | FieldValue::Block(Some(items)) => Some(items),
428            _ => None,
429        }
430    }
431
432    /// Every grammar expression this form holds directly, operations included.
433    pub fn for_each_expression<'a>(&'a self, visit: &mut impl FnMut(&'a GrammarExpr)) {
434        for value in &self.fields {
435            match value {
436                FieldValue::Expression(expr) => visit(expr),
437                FieldValue::Expressions(items) => items.iter().for_each(&mut *visit),
438                FieldValue::Operation(operation) => operation.for_each_expression(visit),
439                FieldValue::Operations(items) | FieldValue::Block(Some(items)) => {
440                    for operation in items {
441                        operation.for_each_expression(visit);
442                    }
443                }
444                _ => {}
445            }
446        }
447    }
448
449    /// Rewrites every grammar expression this form holds, operations included.
450    pub fn map_expressions(&mut self, map: &mut impl FnMut(&mut GrammarExpr)) {
451        for value in &mut self.fields {
452            match value {
453                FieldValue::Expression(expr) => map(expr),
454                FieldValue::Expressions(items) => items.iter_mut().for_each(&mut *map),
455                FieldValue::Operation(operation) => operation.map_expressions(map),
456                FieldValue::Operations(items) | FieldValue::Block(Some(items)) => {
457                    for operation in items {
458                        operation.map_expressions(map);
459                    }
460                }
461                _ => {}
462            }
463        }
464    }
465}
466
467/// One item of a byte class.
468#[derive(Clone, Copy, Debug, PartialEq, Eq)]
469pub enum ByteClassItem {
470    /// One byte.
471    Byte(u8),
472    /// An inclusive byte range.
473    Range(u8, u8),
474}
475
476/// One item of a character class that names Unicode properties.
477#[derive(Clone, Debug, PartialEq, Eq)]
478pub enum UnicodeClassItem {
479    /// A single character.
480    Char(char),
481    /// An inclusive character range.
482    Range(char, char),
483    /// A Unicode general category such as `Lu` or `L`.
484    Category(String),
485    /// A Unicode script such as `Greek` or `Han`.
486    Script(String),
487}
488
489/// A character class: a plain [`GrammarExpr::CharClass`] when every item is a
490/// character or a range, otherwise a [`FeatureExpr::UnicodeClass`].
491#[must_use]
492pub fn class_expression(negated: bool, items: Vec<UnicodeClassItem>) -> GrammarExpr {
493    let plain = items
494        .iter()
495        .map(|item| match item {
496            UnicodeClassItem::Char(value) => Some(CharClassItem::Char(*value)),
497            UnicodeClassItem::Range(start, end) => Some(CharClassItem::Range(*start, *end)),
498            UnicodeClassItem::Category(_) | UnicodeClassItem::Script(_) => None,
499        })
500        .collect::<Option<Vec<_>>>();
501    plain.map_or_else(
502        || GrammarExpr::feature(FeatureExpr::UnicodeClass { negated, items }),
503        |items| GrammarExpr::CharClass { negated, items },
504    )
505}
506
507/// An expression of the grammar feature union.
508#[derive(Clone, Debug, PartialEq, Eq)]
509pub enum FeatureExpr {
510    /// A form of [`FEATURE_EXPRESSION_FORMS`].
511    Form(FeatureForm),
512    /// A class of bytes, `byteClass` or `notByteClass`.
513    ByteClass {
514        /// Whether the class is negated.
515        negated: bool,
516        /// Bytes and byte ranges of the class.
517        items: Vec<ByteClassItem>,
518    },
519    /// A character class with at least one Unicode `category` or `script` item.
520    UnicodeClass {
521        /// Whether the class is negated.
522        negated: bool,
523        /// Characters, ranges, categories and scripts of the class.
524        items: Vec<UnicodeClassItem>,
525    },
526    /// A call of a parameterized rule, `ref(NAME, ARGUMENT, ...)`.
527    Call {
528        /// The called rule.
529        name: String,
530        /// The arguments, at least one.
531        arguments: Vec<GrammarExpr>,
532    },
533}
534
535impl FeatureExpr {
536    /// The head word of this expression in the native listing.
537    #[must_use]
538    pub fn head(&self) -> &str {
539        match self {
540            Self::Form(form) => &form.head,
541            Self::ByteClass { .. } => "byteClass",
542            Self::UnicodeClass { .. } => "charClass",
543            Self::Call { .. } => "ref",
544        }
545    }
546
547    /// Every grammar expression this one holds directly, operations included.
548    pub fn for_each_expression<'a>(&'a self, visit: &mut impl FnMut(&'a GrammarExpr)) {
549        match self {
550            Self::Form(form) => form.for_each_expression(visit),
551            Self::Call { arguments, .. } => arguments.iter().for_each(visit),
552            Self::ByteClass { .. } | Self::UnicodeClass { .. } => {}
553        }
554    }
555
556    /// Rewrites every grammar expression this one holds directly.
557    pub fn map_expressions(&mut self, map: &mut impl FnMut(&mut GrammarExpr)) {
558        match self {
559            Self::Form(form) => form.map_expressions(map),
560            Self::Call { arguments, .. } => arguments.iter_mut().for_each(map),
561            Self::ByteClass { .. } | Self::UnicodeClass { .. } => {}
562        }
563    }
564
565    /// Adds the rule names this expression references, as the JavaScript
566    /// `collectReferences` does: calls and the expressions of `item`,
567    /// `items`, `arguments` and `synchronize` fields.
568    pub(crate) fn collect_references(&self, names: &mut BTreeSet<String>) {
569        match self {
570            Self::Call { name, arguments } => {
571                names.insert(name.clone());
572                for argument in arguments {
573                    argument.collect_nonterminals(names);
574                }
575            }
576            Self::Form(form) => {
577                for value in &form.fields {
578                    match value {
579                        FieldValue::Expression(expr) => expr.collect_nonterminals(names),
580                        FieldValue::Expressions(items) => {
581                            for item in items {
582                                item.collect_nonterminals(names);
583                            }
584                        }
585                        _ => {}
586                    }
587                }
588            }
589            Self::ByteClass { .. } | Self::UnicodeClass { .. } => {}
590        }
591    }
592}
593
594/// The optional parts of a rule the feature union adds.
595#[derive(Clone, Debug, Default, PartialEq, Eq)]
596pub struct RuleAttributes {
597    /// The rule's parameters; empty for a rule without.
598    pub parameters: Vec<String>,
599    /// The channel; a channel other than `default` makes the rule trivia.
600    pub channel: Option<String>,
601    /// The lexer modes the rule may match in.
602    pub modes: Option<Vec<String>>,
603    /// The semantic action, a statement list.
604    pub action: Option<Vec<Operation>>,
605}
606
607impl RuleAttributes {
608    /// Whether no attribute is set.
609    #[must_use]
610    pub fn is_empty(&self) -> bool {
611        self == &Self::default()
612    }
613}
614
615/// A macro declaration: `macro NAME(P, ...) = EXPRESSION`.
616#[derive(Clone, Debug, PartialEq, Eq)]
617pub struct GrammarMacro {
618    /// The macro name.
619    pub name: String,
620    /// The macro parameters.
621    pub parameters: Vec<String>,
622    /// The macro body.
623    pub expression: GrammarExpr,
624}
625
626/// An external scanner declaration.
627#[derive(Clone, Debug, PartialEq, Eq)]
628pub struct GrammarScanner {
629    /// The scanner name.
630    pub name: String,
631    /// The tokens the scanner produces.
632    pub tokens: Vec<String>,
633    /// The scanner's statements.
634    pub operations: Vec<Operation>,
635}
636
637/// One entry of a precedence order: a named precedence or a rule, whose
638/// productions it ranks.
639#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
640pub enum PrecedenceEntry {
641    /// The precedence `namedPrecedence` gives this name.
642    Name(String),
643    /// Every precedence of this rule's productions.
644    Rule(String),
645}
646
647impl PrecedenceEntry {
648    /// Builds an entry from its kind word, `name` or `rule`, and its value.
649    #[must_use]
650    pub fn from_kind(kind: &str, value: String) -> Option<Self> {
651        match kind {
652            "name" => Some(Self::Name(value)),
653            "rule" => Some(Self::Rule(value)),
654            _ => None,
655        }
656    }
657
658    /// The entry's kind word, `name` or `rule`.
659    #[must_use]
660    pub const fn kind(&self) -> &'static str {
661        match self {
662            Self::Name(_) => "name",
663            Self::Rule(_) => "rule",
664        }
665    }
666
667    /// The precedence or rule name.
668    #[must_use]
669    pub fn value(&self) -> &str {
670        match self {
671            Self::Name(value) | Self::Rule(value) => value,
672        }
673    }
674}
675
676/// The grammar-level declarations of the feature union.
677#[derive(Clone, Debug, Default, PartialEq, Eq)]
678pub struct GrammarDeclarations {
679    /// `generalized`, `peg` or `longest`, when given.
680    pub matching: Option<String>,
681    /// The settling steps (see [`SETTLING_STEPS`]), when given.
682    pub settling: Option<Vec<String>>,
683    /// Names of grammars this one inherits from.
684    pub imports: Vec<String>,
685    /// The lexer modes beyond `default`.
686    pub modes: Vec<String>,
687    /// Trivia expressions allowed between any two tokens.
688    pub extras: Vec<GrammarExpr>,
689    /// Groups of rule names whose ambiguity is expected.
690    pub conflicts: Vec<Vec<String>>,
691    /// Orders of named precedences and rules, the earlier entry higher.
692    pub precedences: Vec<Vec<PrecedenceEntry>>,
693    /// Macro declarations.
694    pub macros: Vec<GrammarMacro>,
695    /// External scanner declarations.
696    pub scanners: Vec<GrammarScanner>,
697}
698
699impl GrammarDeclarations {
700    /// Whether no declaration is given.
701    #[must_use]
702    pub fn is_empty(&self) -> bool {
703        self == &Self::default()
704    }
705
706    /// The token names the external scanners produce.
707    #[must_use]
708    pub fn external_tokens(&self) -> Vec<&str> {
709        self.scanners
710            .iter()
711            .flat_map(|scanner| scanner.tokens.iter().map(String::as_str))
712            .collect()
713    }
714
715    /// The names of the declaration kinds that are given, in listing order.
716    #[must_use]
717    pub fn present(&self) -> Vec<&'static str> {
718        let mut present = Vec::new();
719        if self.matching.is_some() {
720            present.push("matching");
721        }
722        if self.settling.is_some() {
723            present.push("settling");
724        }
725        for (name, empty) in [
726            ("imports", self.imports.is_empty()),
727            ("modes", self.modes.is_empty()),
728            ("extras", self.extras.is_empty()),
729            ("conflicts", self.conflicts.is_empty()),
730            ("precedences", self.precedences.is_empty()),
731            ("macros", self.macros.is_empty()),
732            ("scanners", self.scanners.is_empty()),
733        ] {
734            if !empty {
735                present.push(name);
736            }
737        }
738        present
739    }
740}