meta_language/grammar/merge/
rename.rs1use std::collections::{BTreeMap, BTreeSet};
4
5use super::normalize::quote;
6use super::{GrammarRenameError, GrammarRenameErrorKind, RenamedGrammar, RuleAlias};
7use crate::grammar::{
8 FeatureExpr, Grammar, GrammarDeclarations, GrammarExpr, GrammarMacro, GrammarRule,
9 GrammarScanner, Operation, PrecedenceEntry,
10};
11
12pub fn rename_grammar_rule(
20 grammar: &Grammar,
21 from: &str,
22 to: &str,
23 namespace: Option<&str>,
24 aliases: &[RuleAlias],
25) -> Result<RenamedGrammar, GrammarRenameError> {
26 if to.is_empty() || to.chars().any(char::is_whitespace) {
27 return Err(GrammarRenameError::new(
28 GrammarRenameErrorKind::InvalidName,
29 format!("invalid rule name {}", quote(to)),
30 ));
31 }
32 if grammar.rule(from).is_none() {
33 return Err(GrammarRenameError::new(
34 GrammarRenameErrorKind::UnknownRule,
35 format!("grammar has no rule {from}"),
36 ));
37 }
38 if from == to {
39 return Ok(RenamedGrammar {
40 grammar: grammar.clone(),
41 aliases: aliases.to_vec(),
42 });
43 }
44 let mut mapping = vec![(from.to_owned(), to.to_owned())];
45 if let Some(namespace) = namespace {
46 mapping.push((format!("{namespace}.{from}"), format!("{namespace}.{to}")));
47 mapping.push((format!("{namespace}::{from}"), format!("{namespace}::{to}")));
48 }
49 let mut taken = grammar.referenced_nonterminals();
50 taken.extend(grammar.rules().iter().map(|rule| rule.name.clone()));
51 if let Some((_, target)) = mapping.iter().find(|(_, target)| taken.contains(target)) {
52 return Err(GrammarRenameError::new(
53 GrammarRenameErrorKind::Collision,
54 format!("renaming {from} to {to} would capture the existing name {target}"),
55 ));
56 }
57 let mut chained = false;
58 let mut next_aliases: Vec<RuleAlias> = aliases
59 .iter()
60 .map(|alias| {
61 if alias.canonical == from {
62 chained = true;
63 RuleAlias {
64 canonical: to.to_owned(),
65 original: alias.original.clone(),
66 }
67 } else {
68 alias.clone()
69 }
70 })
71 .collect();
72 if !chained {
73 next_aliases.push(RuleAlias {
74 canonical: to.to_owned(),
75 original: from.to_owned(),
76 });
77 }
78 Ok(RenamedGrammar {
79 grammar: rename_all(grammar, &mapping.into_iter().collect()),
80 aliases: next_aliases,
81 })
82}
83
84pub fn restore_source_names(
86 grammar: &Grammar,
87 aliases: &[RuleAlias],
88 namespace: Option<&str>,
89) -> Result<Grammar, GrammarRenameError> {
90 let mut mapping = BTreeMap::new();
91 for RuleAlias {
92 canonical,
93 original,
94 } in aliases
95 {
96 if grammar.rule(canonical).is_none() || canonical == original {
97 continue;
98 }
99 mapping.insert(canonical.clone(), original.clone());
100 if let Some(namespace) = namespace {
101 mapping.insert(
102 format!("{namespace}.{canonical}"),
103 format!("{namespace}.{original}"),
104 );
105 mapping.insert(
106 format!("{namespace}::{canonical}"),
107 format!("{namespace}::{original}"),
108 );
109 }
110 }
111 let rename = |name: &str| {
112 mapping
113 .get(name)
114 .cloned()
115 .unwrap_or_else(|| name.to_owned())
116 };
117 let rule_names: Vec<String> = grammar
118 .rules()
119 .iter()
120 .map(|rule| rename(&rule.name))
121 .collect();
122 let unique: BTreeSet<&String> = rule_names.iter().collect();
123 let captured = grammar
124 .referenced_nonterminals()
125 .iter()
126 .filter(|name| grammar.rule(name).is_none())
127 .any(|name| rule_names.contains(&rename(name)));
128 if unique.len() != rule_names.len() || captured {
129 return Err(GrammarRenameError::new(
130 GrammarRenameErrorKind::Collision,
131 "restoring source names would give two bindings the same name",
132 ));
133 }
134 Ok(rename_all(grammar, &mapping))
135}
136
137fn rename_all(grammar: &Grammar, mapping: &BTreeMap<String, String>) -> Grammar {
143 let rename = |name: &str| {
144 mapping
145 .get(name)
146 .cloned()
147 .unwrap_or_else(|| name.to_owned())
148 };
149 let mut renamed = Grammar::new();
150 for rule in grammar.rules() {
151 renamed.add_rule(GrammarRule {
152 name: rename(&rule.name),
153 ..renamed_rule(rule, &rename)
154 });
155 }
156 if let Some(start) = grammar.start() {
157 renamed.set_start(rename(start));
158 }
159 renamed.source_format = grammar.source_format();
160 renamed.set_declarations(map_declarations(grammar.declarations(), &rename));
161 renamed
162}
163
164pub(super) fn renamed_rule(rule: &GrammarRule, rename: &dyn Fn(&str) -> String) -> GrammarRule {
166 let mut attributes = rule.attributes.clone();
167 if let Some(action) = &rule.attributes.action {
168 attributes.action = Some(map_operations(action, rename));
169 }
170 GrammarRule {
171 name: rule.name.clone(),
172 expr: map_references(&rule.expr, rename),
173 kind: rule.kind,
174 concept: rule.concept.clone(),
175 source_names: rule.source_names.clone(),
176 doc: rule.doc.clone(),
177 attributes,
178 }
179}
180
181pub(super) fn map_declarations(
183 declarations: &GrammarDeclarations,
184 rename: &dyn Fn(&str) -> String,
185) -> GrammarDeclarations {
186 GrammarDeclarations {
187 matching: declarations.matching.clone(),
188 settling: declarations.settling.clone(),
189 imports: declarations.imports.clone(),
190 modes: declarations.modes.clone(),
191 extras: declarations
192 .extras
193 .iter()
194 .map(|extra| map_references(extra, rename))
195 .collect(),
196 conflicts: declarations
197 .conflicts
198 .iter()
199 .map(|group| group.iter().map(|name| rename(name)).collect())
200 .collect(),
201 precedences: declarations
202 .precedences
203 .iter()
204 .map(|order| {
205 order
206 .iter()
207 .map(|entry| match entry {
208 PrecedenceEntry::Rule(name) => PrecedenceEntry::Rule(rename(name)),
209 PrecedenceEntry::Name(_) => entry.clone(),
210 })
211 .collect()
212 })
213 .collect(),
214 macros: declarations
215 .macros
216 .iter()
217 .map(|declared| GrammarMacro {
218 name: declared.name.clone(),
219 parameters: declared.parameters.clone(),
220 expression: map_references(&declared.expression, rename),
221 })
222 .collect(),
223 scanners: declarations
224 .scanners
225 .iter()
226 .map(|scanner| GrammarScanner {
227 name: scanner.name.clone(),
228 tokens: scanner.tokens.clone(),
229 operations: map_operations(&scanner.operations, rename),
230 })
231 .collect(),
232 }
233}
234
235pub(super) fn map_operations(
237 operations: &[Operation],
238 rename: &dyn Fn(&str) -> String,
239) -> Vec<Operation> {
240 operations
241 .iter()
242 .map(|operation| {
243 let mut copy = operation.clone();
244 copy.map_expressions(&mut |expr| *expr = map_references(expr, rename));
245 copy
246 })
247 .collect()
248}
249
250pub(super) fn map_references(expr: &GrammarExpr, rename: &dyn Fn(&str) -> String) -> GrammarExpr {
251 let map = |inner: &GrammarExpr| Box::new(map_references(inner, rename));
252 match expr {
253 GrammarExpr::NonTerminal(name) => GrammarExpr::NonTerminal(rename(name)),
254 GrammarExpr::Choice {
255 ordered,
256 alternatives,
257 } => GrammarExpr::Choice {
258 ordered: *ordered,
259 alternatives: alternatives
260 .iter()
261 .map(|item| map_references(item, rename))
262 .collect(),
263 },
264 GrammarExpr::Sequence(items) => GrammarExpr::Sequence(
265 items
266 .iter()
267 .map(|item| map_references(item, rename))
268 .collect(),
269 ),
270 GrammarExpr::Optional(inner) => GrammarExpr::Optional(map(inner)),
271 GrammarExpr::ZeroOrMore(inner) => GrammarExpr::ZeroOrMore(map(inner)),
272 GrammarExpr::OneOrMore(inner) => GrammarExpr::OneOrMore(map(inner)),
273 GrammarExpr::Repeat { expr, min, max } => GrammarExpr::Repeat {
274 expr: map(expr),
275 min: *min,
276 max: *max,
277 },
278 GrammarExpr::And(inner) => GrammarExpr::And(map(inner)),
279 GrammarExpr::Not(inner) => GrammarExpr::Not(map(inner)),
280 GrammarExpr::Capture { label, expr } => GrammarExpr::Capture {
281 label: label.clone(),
282 expr: map(expr),
283 },
284 GrammarExpr::Feature(feature) => {
285 let mut copy =
286 GrammarExpr::rewrite_feature(feature, |inner| map_references(inner, rename));
287 if let GrammarExpr::Feature(renamed) = &mut copy
288 && let FeatureExpr::Call { name, .. } = renamed.as_mut()
289 {
290 *name = rename(name);
291 }
292 copy
293 }
294 other => other.clone(),
295 }
296}