Skip to main content

meta_language/grammar/
concepts.rs

1//! Concept-ontology alignment for grammar algebra nodes.
2
3use super::{Grammar, GrammarExpr, GrammarRule};
4use crate::link_network::LinkNetwork;
5
6/// A grammar-algebra concept with a stable id and per-format surface forms.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct GrammarConcept {
9    /// Stable language-free concept identifier.
10    pub id: &'static str,
11    /// Human-readable definition of the grammar construct.
12    pub definition: &'static str,
13    /// Concrete syntax examples keyed by grammar format.
14    pub syntax: &'static [(&'static str, &'static str)],
15}
16
17/// Grammar construct concepts aligned with [`GrammarExpr`] variants and rules.
18pub const GRAMMAR_CONCEPTS: &[GrammarConcept] = &[
19    GrammarConcept {
20        id: "grammar.rule",
21        definition: "A named grammar production that binds a non-terminal to an expression.",
22        syntax: &[
23            ("bnf", "::="),
24            ("ebnf", "="),
25            ("abnf", "="),
26            ("peg", "="),
27            ("meta-language", "rule"),
28        ],
29    },
30    GrammarConcept {
31        id: "grammar.sequence",
32        definition: "An ordered concatenation of grammar expressions.",
33        syntax: &[
34            ("bnf", "a b"),
35            ("ebnf", "a , b"),
36            ("peg", "a b"),
37            ("gbnf", "a b"),
38            ("meta-language", "sequence"),
39        ],
40    },
41    GrammarConcept {
42        id: "grammar.ordered-choice",
43        definition: "A prioritized grammar alternative where earlier matches win.",
44        syntax: &[("peg", "/"), ("meta-language", "ordered choice")],
45    },
46    GrammarConcept {
47        id: "grammar.unordered-choice",
48        definition: "A grammar alternative whose branches are not semantically prioritized.",
49        syntax: &[
50            ("bnf", "|"),
51            ("ebnf", "|"),
52            ("abnf", "/"),
53            ("antlr", "|"),
54            ("lark", "|"),
55            ("meta-language", "unordered choice"),
56        ],
57    },
58    GrammarConcept {
59        id: "grammar.counted-repetition",
60        definition: "A counted repetition with explicit minimum and optional maximum bounds.",
61        syntax: &[
62            ("ebnf", "{ }"),
63            ("abnf", "m*n"),
64            ("gbnf", "{m,n}"),
65            ("meta-language", "counted repetition"),
66        ],
67    },
68    GrammarConcept {
69        id: "grammar.zero-or-more-repetition",
70        definition: "A repetition that accepts zero or more occurrences.",
71        syntax: &[
72            ("peg", "*"),
73            ("ebnf", "{ }"),
74            ("antlr", "*"),
75            ("lark", "*"),
76            ("gbnf", "*"),
77        ],
78    },
79    GrammarConcept {
80        id: "grammar.one-or-more-repetition",
81        definition: "A repetition that accepts one or more occurrences.",
82        syntax: &[
83            ("peg", "+"),
84            ("antlr", "+"),
85            ("lark", "+"),
86            ("gbnf", "+"),
87            ("meta-language", "one or more repetition"),
88        ],
89    },
90    GrammarConcept {
91        id: "grammar.optional-expression",
92        definition: "An expression that may be present or absent.",
93        syntax: &[
94            ("ebnf", "[ ]"),
95            ("abnf", "[ ]"),
96            ("peg", "?"),
97            ("antlr", "?"),
98            ("lark", "?"),
99        ],
100    },
101    GrammarConcept {
102        id: "grammar.terminal",
103        definition: "A literal terminal token matched directly in the input.",
104        syntax: &[
105            ("bnf", "\"lit\""),
106            ("ebnf", "\"lit\""),
107            ("abnf", "%i\"lit\""),
108            ("peg", "\"lit\""),
109            ("lark", "\"lit\""),
110            ("tree-sitter", "token"),
111        ],
112    },
113    GrammarConcept {
114        id: "grammar.nonterminal",
115        definition: "A reference to another named grammar rule.",
116        syntax: &[
117            ("bnf", "<name>"),
118            ("ebnf", "name"),
119            ("peg", "name"),
120            ("antlr", "name"),
121            ("lark", "name"),
122            ("meta-language", "nonterminal"),
123        ],
124    },
125    GrammarConcept {
126        id: "grammar.character-class",
127        definition: "A set of characters accepted at one input position.",
128        syntax: &[
129            ("peg", "[a-z]"),
130            ("antlr", "[a-z]"),
131            ("lark", "/[a-z]/"),
132            ("gbnf", "[^...]"),
133            ("meta-language", "character class"),
134        ],
135    },
136    GrammarConcept {
137        id: "grammar.character-range",
138        definition: "An inclusive range between two character endpoints.",
139        syntax: &[
140            ("abnf", "%x30-39"),
141            ("lark", "\"a\"..\"z\""),
142            ("meta-language", "'a'..='z'"),
143        ],
144    },
145    GrammarConcept {
146        id: "grammar.any-character",
147        definition: "A wildcard grammar expression that accepts any single character.",
148        syntax: &[
149            ("peg", "."),
150            ("lark", "."),
151            ("gbnf", "."),
152            ("meta-language", "any character"),
153        ],
154    },
155    GrammarConcept {
156        id: "grammar.positive-predicate",
157        definition: "A positive lookahead predicate that tests an expression without consuming input.",
158        syntax: &[("peg", "&e"), ("meta-language", "positive predicate")],
159    },
160    GrammarConcept {
161        id: "grammar.negative-predicate",
162        definition: "A negative lookahead predicate that rejects when an expression would match.",
163        syntax: &[("peg", "!e"), ("meta-language", "negative predicate")],
164    },
165    GrammarConcept {
166        id: "grammar.capture",
167        definition: "A labelled or anonymous capture of a grammar subexpression.",
168        syntax: &[
169            ("meta-language", "name:e"),
170            ("antlr", "label=e"),
171            ("lark", "name:e"),
172        ],
173    },
174    GrammarConcept {
175        id: "grammar.empty-expression",
176        definition: "A grammar expression that accepts the empty string.",
177        syntax: &[
178            ("bnf", "empty alternative"),
179            ("ebnf", "empty alternative"),
180            ("meta-language", "empty expression"),
181        ],
182    },
183];
184
185/// Concept id for a [`GrammarExpr`] variant.
186#[must_use]
187pub const fn grammar_expr_concept_id(expr: &GrammarExpr) -> &'static str {
188    match expr {
189        GrammarExpr::Empty => "grammar.empty-expression",
190        GrammarExpr::Terminal(_) | GrammarExpr::TerminalInsensitive(_) => "grammar.terminal",
191        GrammarExpr::CharRange(_, _) => "grammar.character-range",
192        GrammarExpr::CharClass { .. } => "grammar.character-class",
193        GrammarExpr::AnyChar => "grammar.any-character",
194        GrammarExpr::NonTerminal(_) => "grammar.nonterminal",
195        GrammarExpr::Choice { ordered: true, .. } => "grammar.ordered-choice",
196        GrammarExpr::Choice { ordered: false, .. } => "grammar.unordered-choice",
197        GrammarExpr::Sequence(_) => "grammar.sequence",
198        GrammarExpr::Optional(_) => "grammar.optional-expression",
199        GrammarExpr::ZeroOrMore(_) => "grammar.zero-or-more-repetition",
200        GrammarExpr::OneOrMore(_) => "grammar.one-or-more-repetition",
201        GrammarExpr::Repeat { .. } => "grammar.counted-repetition",
202        GrammarExpr::And(_) => "grammar.positive-predicate",
203        GrammarExpr::Not(_) => "grammar.negative-predicate",
204        GrammarExpr::Capture { .. } => "grammar.capture",
205        // The feature union forms share one concept record.
206        GrammarExpr::Feature(_) => "grammar.feature-union-form",
207    }
208}
209
210/// Concept id for a rule: its explicit concept, or its top-level expression concept.
211#[must_use]
212pub fn rule_concept_id(rule: &GrammarRule) -> Option<&str> {
213    rule.concept()
214        .map_or_else(|| Some(grammar_expr_concept_id(rule.expr())), Some)
215}
216
217/// Fills missing rule-level concept alignments from each rule's top-level expression.
218pub fn annotate_grammar_concepts(grammar: &mut Grammar) {
219    for rule in &mut grammar.rules {
220        if rule.concept.is_none() {
221            rule.concept = Some(grammar_expr_concept_id(&rule.expr).to_owned());
222        }
223    }
224}
225
226impl LinkNetwork {
227    /// Seeds only the grammar-construct concept ontology layer.
228    #[must_use]
229    pub fn seed_grammar_concept_ontology(&mut self) -> usize {
230        for concept in GRAMMAR_CONCEPTS {
231            let concept_link = self.intern_concept(concept.id, Some(concept.definition));
232            self.insert_former_concept_ids(concept_link, concept.id);
233
234            for (language, syntax) in concept.syntax {
235                self.insert_concept_syntax_mapping(
236                    concept_link,
237                    concept.id,
238                    language,
239                    syntax,
240                    true,
241                );
242            }
243        }
244
245        GRAMMAR_CONCEPTS.len()
246    }
247}