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", "choice"),
56 ],
57 },
58 GrammarConcept {
59 id: "grammar.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", "repeat"),
66 ],
67 },
68 GrammarConcept {
69 id: "grammar.zero-or-more",
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",
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"),
88 ],
89 },
90 GrammarConcept {
91 id: "grammar.optional",
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.non-terminal",
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", "non-terminal"),
123 ],
124 },
125 GrammarConcept {
126 id: "grammar.char-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.char-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-char",
147 definition: "A wildcard grammar expression that accepts any single character.",
148 syntax: &[
149 ("peg", "."),
150 ("lark", "."),
151 ("gbnf", "."),
152 ("meta-language", "any"),
153 ],
154 },
155 GrammarConcept {
156 id: "grammar.positive-predicate",
157 definition:
158 "A positive lookahead predicate that tests an expression without consuming input.",
159 syntax: &[("peg", "&e"), ("meta-language", "and predicate")],
160 },
161 GrammarConcept {
162 id: "grammar.negative-predicate",
163 definition: "A negative lookahead predicate that rejects when an expression would match.",
164 syntax: &[("peg", "!e"), ("meta-language", "not predicate")],
165 },
166 GrammarConcept {
167 id: "grammar.capture",
168 definition: "A labelled or anonymous capture of a grammar subexpression.",
169 syntax: &[
170 ("meta-language", "name:e"),
171 ("antlr", "label=e"),
172 ("lark", "name:e"),
173 ],
174 },
175 GrammarConcept {
176 id: "grammar.empty",
177 definition: "A grammar expression that accepts the empty string.",
178 syntax: &[
179 ("bnf", "empty alternative"),
180 ("ebnf", "empty alternative"),
181 ("meta-language", "empty"),
182 ],
183 },
184];
185
186#[must_use]
188pub const fn grammar_expr_concept_id(expr: &GrammarExpr) -> &'static str {
189 match expr {
190 GrammarExpr::Empty => "grammar.empty",
191 GrammarExpr::Terminal(_) | GrammarExpr::TerminalInsensitive(_) => "grammar.terminal",
192 GrammarExpr::CharRange(_, _) => "grammar.char-range",
193 GrammarExpr::CharClass { .. } => "grammar.char-class",
194 GrammarExpr::AnyChar => "grammar.any-char",
195 GrammarExpr::NonTerminal(_) => "grammar.non-terminal",
196 GrammarExpr::Choice { ordered: true, .. } => "grammar.ordered-choice",
197 GrammarExpr::Choice { ordered: false, .. } => "grammar.unordered-choice",
198 GrammarExpr::Sequence(_) => "grammar.sequence",
199 GrammarExpr::Optional(_) => "grammar.optional",
200 GrammarExpr::ZeroOrMore(_) => "grammar.zero-or-more",
201 GrammarExpr::OneOrMore(_) => "grammar.one-or-more",
202 GrammarExpr::Repeat { .. } => "grammar.repetition",
203 GrammarExpr::And(_) => "grammar.positive-predicate",
204 GrammarExpr::Not(_) => "grammar.negative-predicate",
205 GrammarExpr::Capture { .. } => "grammar.capture",
206 }
207}
208
209#[must_use]
211pub fn rule_concept_id(rule: &GrammarRule) -> Option<&str> {
212 rule.concept()
213 .map_or_else(|| Some(grammar_expr_concept_id(rule.expr())), Some)
214}
215
216pub fn annotate_grammar_concepts(grammar: &mut Grammar) {
218 for rule in &mut grammar.rules {
219 if rule.concept.is_none() {
220 rule.concept = Some(grammar_expr_concept_id(&rule.expr).to_owned());
221 }
222 }
223}
224
225impl LinkNetwork {
226 #[must_use]
228 pub fn seed_grammar_concept_ontology(&mut self) -> usize {
229 for concept in GRAMMAR_CONCEPTS {
230 let concept_link = self.intern_concept(concept.id, Some(concept.definition));
231
232 for (language, syntax) in concept.syntax {
233 self.insert_concept_syntax_mapping(
234 concept_link,
235 concept.id,
236 language,
237 syntax,
238 true,
239 );
240 }
241 }
242
243 GRAMMAR_CONCEPTS.len()
244 }
245}