metrale_grammar/grammar/functor/
structure_normalizer.rs1use super::mutator::{MutatorState, OwnedExpr, rebuild_tag_dispatch};
11use super::normalizer::SingleElementExprEliminator;
12use crate::grammar::data::GrammarData;
13use crate::grammar::expr::GrammarExprType;
14
15#[derive(Default)]
17pub struct StructureNormalizer {
18 state: Option<MutatorState>,
19}
20
21impl StructureNormalizer {
22 pub fn apply(grammar: GrammarData) -> GrammarData {
24 let grammar = SingleElementExprEliminator::apply(grammar);
25 let mut p = Self::default();
26 *p.st() = MutatorState::new(grammar);
27 let num_rules = p.st().base.num_rules();
28 for i in 0..num_rules {
29 let name = p.st().base.rule(i).name.clone();
30 p.st().builder.add_empty_rule(name).expect("dup rule");
31 }
32 for i in 0..num_rules {
33 let rule = p.st().base.rule(i).clone();
34 p.st().cur_rule_name = rule.name.clone();
35 let body = p.st().base.owned_expr(rule.body_expr_id);
36 let new_body = p.visit_rule_body(&body);
37 p.st().builder.update_rule_body(i, new_body).expect("range");
38 let la = p.visit_lookahead(rule.lookahead_assertion_id);
39 p.st()
40 .builder
41 .update_lookahead_assertion(i, la)
42 .expect("range");
43 }
44 let root_name = p.st().base.root_rule().name.clone();
45 let builder = std::mem::take(&mut p.st().builder);
46 builder.get(&root_name).expect("root")
47 }
48
49 fn st(&mut self) -> &mut MutatorState {
50 self.state
51 .get_or_insert_with(|| MutatorState::new(GrammarData::new()))
52 }
53
54 fn visit_lookahead(&mut self, id: i32) -> i32 {
55 if id == -1 {
56 return -1;
57 }
58 let e = self.st().base.owned_expr(id);
59 match e.kind {
60 GrammarExprType::Sequence => {
61 let ids = self.visit_sequence_(&e);
62 self.st().builder.add_sequence(&ids)
63 }
64 GrammarExprType::Choices => panic!("Choices in lookahead assertion not supported"),
65 GrammarExprType::EmptyStr => panic!("Empty string in lookahead assertion"),
66 GrammarExprType::TagDispatch => panic!("TagDispatch in lookahead assertion"),
67 _ => {
68 let elem = self.st().builder.add_grammar_expr(e.kind, &e.data);
69 self.st().builder.add_sequence(&[elem])
70 }
71 }
72 }
73
74 fn visit_rule_body(&mut self, e: &OwnedExpr) -> i32 {
75 match e.kind {
76 GrammarExprType::Sequence => {
77 let seq = self.visit_sequence_(e);
78 let s = self.st().builder.add_sequence(&seq);
79 self.st().builder.add_choices(&[s])
80 }
81 GrammarExprType::Choices => {
82 let ids = self.visit_choices_(e);
83 self.st().builder.add_choices(&ids)
84 }
85 GrammarExprType::EmptyStr => {
86 let empty = self.st().builder.add_empty_str();
87 self.st().builder.add_choices(&[empty])
88 }
89 GrammarExprType::TagDispatch => {
90 let td = e.tag_dispatch.clone().expect("td");
91 rebuild_tag_dispatch(&mut self.st().builder, &td)
92 }
93 _ => {
94 let elem = self.st().builder.add_grammar_expr(e.kind, &e.data);
95 let seq = self.st().builder.add_sequence(&[elem]);
96 self.st().builder.add_choices(&[seq])
97 }
98 }
99 }
100
101 fn visit_choices_(&mut self, e: &OwnedExpr) -> Vec<i32> {
103 let mut new_choice_ids: Vec<i32> = Vec::new();
104 let mut found_empty = false;
105 for &i in &e.data {
106 let choice = self.st().base.owned_expr(i);
107 match choice.kind {
108 GrammarExprType::Sequence => {
109 let sub = self.visit_sequence_(&choice);
110 if sub.is_empty() {
111 found_empty = true;
112 } else {
113 let s = self.st().builder.add_sequence(&sub);
114 new_choice_ids.push(s);
115 }
116 }
117 GrammarExprType::Choices => {
118 let sub = self.visit_choices_(&choice);
119 let contains_empty = self.st().builder.get_grammar_expr(sub[0]).kind
120 == GrammarExprType::EmptyStr;
121 if contains_empty {
122 found_empty = true;
123 new_choice_ids.extend_from_slice(&sub[1..]);
124 } else {
125 new_choice_ids.extend_from_slice(&sub);
126 }
127 }
128 GrammarExprType::EmptyStr => found_empty = true,
129 GrammarExprType::TagDispatch => {
130 let td = choice.tag_dispatch.clone().expect("td");
131 let td_id = rebuild_tag_dispatch(&mut self.st().builder, &td);
132 let hint = self.st().cur_rule_name.clone();
133 let new_rule = self
134 .st()
135 .builder
136 .add_rule_with_hint(&hint, td_id)
137 .expect("hint");
138 let rr = self.st().builder.add_rule_ref(new_rule);
139 let s = self.st().builder.add_sequence(&[rr]);
140 new_choice_ids.push(s);
141 }
142 _ => {
143 let sub = self
144 .st()
145 .builder
146 .add_grammar_expr(choice.kind, &choice.data);
147 let s = self.st().builder.add_sequence(&[sub]);
148 new_choice_ids.push(s);
149 }
150 }
151 }
152 if found_empty {
153 let empty = self.st().builder.add_empty_str();
154 new_choice_ids.insert(0, empty);
155 }
156 assert!(!new_choice_ids.is_empty());
157 new_choice_ids
158 }
159
160 fn visit_sequence_(&mut self, e: &OwnedExpr) -> Vec<i32> {
162 let mut new_seq: Vec<i32> = Vec::new();
163 for &i in &e.data {
164 let elem = self.st().base.owned_expr(i);
165 match elem.kind {
166 GrammarExprType::Sequence => {
167 let sub = self.visit_sequence_(&elem);
168 new_seq.extend_from_slice(&sub);
169 }
170 GrammarExprType::Choices => {
171 let sub = self.visit_choices_(&elem);
172 if sub.len() == 1 {
173 let ce = self.st().builder.get_grammar_expr(sub[0]);
174 if ce.kind != GrammarExprType::EmptyStr {
175 let data: Vec<i32> = ce.data.to_vec();
176 new_seq.extend_from_slice(&data);
177 }
178 } else {
179 let c = self.st().builder.add_choices(&sub);
180 let hint = self.st().cur_rule_name.clone();
181 let nr = self
182 .st()
183 .builder
184 .add_rule_with_hint(&hint, c)
185 .expect("hint");
186 new_seq.push(self.st().builder.add_rule_ref(nr));
187 }
188 }
189 GrammarExprType::EmptyStr => {}
190 GrammarExprType::TagDispatch => {
191 let td = elem.tag_dispatch.clone().expect("td");
192 let td_id = rebuild_tag_dispatch(&mut self.st().builder, &td);
193 let hint = self.st().cur_rule_name.clone();
194 let nr = self
195 .st()
196 .builder
197 .add_rule_with_hint(&hint, td_id)
198 .expect("hint");
199 new_seq.push(self.st().builder.add_rule_ref(nr));
200 }
201 _ => {
202 let s = self.st().builder.add_grammar_expr(elem.kind, &elem.data);
203 new_seq.push(s);
204 }
205 }
206 }
207 new_seq
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214 use crate::grammar::parse_ebnf_default;
215 use crate::grammar::printer::print_grammar;
216
217 #[test]
218 fn body_becomes_choices_of_sequences() {
219 let g = parse_ebnf_default("root ::= \"a\" \"b\"\n").unwrap();
220 let n = StructureNormalizer::apply(g);
221 let out = print_grammar(&n);
222 assert!(out.starts_with("root ::= ("), "{out}");
224 }
225
226 #[test]
227 fn nested_choices_flattened() {
228 let g = parse_ebnf_default("root ::= \"a\" | (\"b\" | \"c\")\n").unwrap();
229 let n = StructureNormalizer::apply(g);
230 let out = print_grammar(&n);
231 assert!(out.contains(" | "), "{out}");
232 }
233
234 #[test]
235 fn inner_alternation_makes_new_rule() {
236 let g = parse_ebnf_default("root ::= \"a\" (\"b\" | \"c\")\n").unwrap();
237 let n = StructureNormalizer::apply(g);
238 assert!(n.num_rules() >= 2);
239 }
240
241 #[test]
242 fn empty_str_body() {
243 let g = parse_ebnf_default("root ::= \"\"\n").unwrap();
244 let n = StructureNormalizer::apply(g);
245 assert!(print_grammar(&n).contains("\"\""));
246 }
247}