1use super::{Grammar, GrammarExpr, GrammarRule};
4use crate::link_network::LinkNetwork;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct GrammarConcept {
9 pub id: &'static str,
11 pub definition: &'static str,
13 pub syntax: &'static [(&'static str, &'static str)],
15}
16
17pub 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#[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 GrammarExpr::Feature(_) => "grammar.feature-union-form",
207 }
208}
209
210#[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
217pub 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 #[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}