metrale_grammar/grammar/functor/
optimizer.rs1use std::collections::HashMap;
10
11use super::analyzer::UsedRulesAnalyzer;
12use super::mutator::{GrammarMutator, MutatorState, OwnedExpr, rebuild_tag_dispatch};
13use crate::grammar::data::GrammarData;
14use crate::grammar::expr::GrammarExprType;
15
16#[derive(Default)]
19pub struct ByteStringFuser {
20 state: Option<MutatorState>,
21}
22
23impl ByteStringFuser {
24 pub fn apply(grammar: GrammarData) -> GrammarData {
26 let mut p = Self::default();
27 GrammarMutator::apply(&mut p, grammar)
28 }
29}
30
31impl GrammarMutator for ByteStringFuser {
32 fn state(&mut self) -> &mut MutatorState {
33 self.state
34 .get_or_insert_with(|| MutatorState::new(GrammarData::new()))
35 }
36
37 fn visit_sequence(&mut self, e: &OwnedExpr) -> i32 {
38 let mut new_seq: Vec<i32> = Vec::new();
39 let mut cur_bytes: Vec<i32> = Vec::new();
40 for &i in &e.data {
41 let elem = self.state().base.owned_expr(i);
42 if elem.kind == GrammarExprType::ByteString {
43 cur_bytes.extend_from_slice(&elem.data);
44 } else {
45 if !cur_bytes.is_empty() {
46 let bs = self.state().builder.add_byte_string_bytes(&cur_bytes);
47 new_seq.push(bs);
48 cur_bytes.clear();
49 }
50 let s = self.state().builder.add_grammar_expr(elem.kind, &elem.data);
51 new_seq.push(s);
52 }
53 }
54 if !cur_bytes.is_empty() {
55 let bs = self.state().builder.add_byte_string_bytes(&cur_bytes);
56 new_seq.push(bs);
57 }
58 self.state().builder.add_sequence(&new_seq)
59 }
60}
61
62#[derive(Default)]
65pub struct RuleInliner {
66 state: Option<MutatorState>,
67 can_inline: HashMap<i32, bool>,
68}
69
70impl RuleInliner {
71 pub fn apply(grammar: GrammarData) -> GrammarData {
73 let mut p = Self::default();
74 GrammarMutator::apply(&mut p, grammar)
75 }
76
77 fn check_can_inline(&self, rule_id: i32) -> bool {
78 let base = &self.state_ref().base;
79 let rule = base.rule(rule_id);
80 let body = base.expr(rule.body_expr_id);
81 if body.kind != GrammarExprType::Choices || body.is_empty() {
82 return false;
83 }
84 for &cid in body.data {
85 let choice = base.expr(cid);
86 if choice.kind == GrammarExprType::EmptyStr {
87 return false;
88 }
89 assert_eq!(choice.kind, GrammarExprType::Sequence);
90 for &eid in choice.data {
91 if base.expr(eid).kind == GrammarExprType::RuleRef {
92 return false;
93 }
94 }
95 }
96 true
97 }
98
99 fn state_ref(&self) -> &MutatorState {
100 self.state.as_ref().expect("state initialized")
101 }
102}
103
104impl GrammarMutator for RuleInliner {
105 fn state(&mut self) -> &mut MutatorState {
106 self.state
107 .get_or_insert_with(|| MutatorState::new(GrammarData::new()))
108 }
109
110 fn visit_choices(&mut self, e: &OwnedExpr) -> i32 {
111 let mut new_choice_ids: Vec<i32> = Vec::new();
112 for &cid in &e.data {
113 let choice = self.state().base.owned_expr(cid);
114 if choice.kind == GrammarExprType::EmptyStr {
115 new_choice_ids.push(self.visit_expr_id(cid));
116 continue;
117 }
118 assert_eq!(choice.kind, GrammarExprType::Sequence);
119 let first = self.state().base.owned_expr(choice.data[0]);
120 if first.kind != GrammarExprType::RuleRef {
121 new_choice_ids.push(self.visit_expr(&choice));
122 continue;
123 }
124 let rule_ref_id = first.data[0];
125 if !self.can_inline.contains_key(&rule_ref_id) {
126 let v = self.check_can_inline(rule_ref_id);
127 self.can_inline.insert(rule_ref_id, v);
128 }
129 if !self.can_inline[&rule_ref_id] {
130 new_choice_ids.push(self.visit_expr(&choice));
131 continue;
132 }
133
134 let other: Vec<i32> = choice.data[1..]
136 .iter()
137 .map(|&x| self.visit_expr_id(x))
138 .collect();
139 let ref_body_id = self.state().base.rule(rule_ref_id).body_expr_id;
141 let ref_choices: Vec<i32> = self.state().base.expr(ref_body_id).data.to_vec();
142 for ref_cid in ref_choices {
143 let ref_choice = self.state().base.owned_expr(ref_cid);
144 assert_eq!(ref_choice.kind, GrammarExprType::Sequence);
145 let mut to_add: Vec<i32> = ref_choice
146 .data
147 .iter()
148 .map(|&x| self.visit_expr_id(x))
149 .collect();
150 to_add.extend_from_slice(&other);
151 let s = self.state().builder.add_sequence(&to_add);
152 new_choice_ids.push(s);
153 }
154 }
155 self.state().builder.add_choices(&new_choice_ids)
156 }
157}
158
159#[derive(Default)]
161pub struct DeadCodeEliminator {
162 state: Option<MutatorState>,
163 rule_id_map: HashMap<i32, i32>,
164}
165
166impl DeadCodeEliminator {
167 pub fn apply(grammar: GrammarData) -> GrammarData {
169 let mut p = Self::default();
170 *p.st() = MutatorState::new(grammar);
171 let used = UsedRulesAnalyzer::apply(&p.st().base);
172 for &rule_id in &used {
173 let name = p.st().base.rule(rule_id).name.clone();
174 let new_id = p.st().builder.add_empty_rule(name).expect("dup");
175 p.rule_id_map.insert(rule_id, new_id);
176 }
177 for &rule_id in &used {
178 let rule = p.st().base.rule(rule_id).clone();
179 let new_id = p.rule_id_map[&rule_id];
180 let new_body = p.visit_expr_id(rule.body_expr_id);
181 p.st()
182 .builder
183 .update_rule_body(new_id, new_body)
184 .expect("range");
185 let new_la = p.visit_lookahead(rule.lookahead_assertion_id);
186 p.st()
187 .builder
188 .update_lookahead_assertion(new_id, new_la)
189 .expect("range");
190 }
191 let root_old = p.st().base.root_rule_id();
192 let root_new = p.rule_id_map[&root_old];
193 let builder = std::mem::take(&mut p.st().builder);
194 builder.get_by_id(root_new).expect("root mapped")
195 }
196
197 fn st(&mut self) -> &mut MutatorState {
198 self.state
199 .get_or_insert_with(|| MutatorState::new(GrammarData::new()))
200 }
201}
202
203impl GrammarMutator for DeadCodeEliminator {
204 fn state(&mut self) -> &mut MutatorState {
205 self.st()
206 }
207
208 fn visit_tag_dispatch(&mut self, e: &OwnedExpr) -> i32 {
209 let mut td = e.tag_dispatch.clone().expect("td");
210 for pair in &mut td.tag_rule_pairs {
211 pair.1 = self.rule_id_map[&pair.1];
212 }
213 rebuild_tag_dispatch(&mut self.state().builder, &td)
214 }
215
216 fn visit_rule_ref(&mut self, e: &OwnedExpr) -> i32 {
217 let new_id = self.rule_id_map[&e.data[0]];
218 self.state().builder.add_rule_ref(new_id)
219 }
220
221 fn visit_repeat(&mut self, e: &OwnedExpr) -> i32 {
222 let new_id = self.rule_id_map[&e.data[0]];
223 self.state()
224 .builder
225 .add_repeat(new_id, e.data[1], e.data[2])
226 }
227}
228#[path = "optimizer_pipeline.rs"]
229mod optimizer_pipeline;
230pub use optimizer_pipeline::{GrammarOptimizer, RepetitionNormalizer};
231
232#[cfg(test)]
233#[path = "optimizer_tests.rs"]
234mod tests;