metrale_grammar/grammar/functor/
analyzer.rs1use std::collections::{BTreeSet, HashSet, VecDeque};
13
14use crate::grammar::data::GrammarData;
15use crate::grammar::expr::GrammarExprType;
16
17pub struct UsedRulesAnalyzer;
21
22impl UsedRulesAnalyzer {
23 pub fn apply(grammar: &GrammarData) -> Vec<i32> {
25 let mut visited: BTreeSet<i32> = BTreeSet::new();
26 let mut queue: VecDeque<i32> = VecDeque::new();
27 queue.push_back(grammar.root_rule_id());
28 while let Some(rule_id) = queue.pop_front() {
29 if !visited.insert(rule_id) {
30 continue;
31 }
32 let rule = grammar.rule(rule_id);
33 collect_refs(grammar, rule.body_expr_id, &mut queue);
34 if rule.lookahead_assertion_id != -1 {
35 collect_refs(grammar, rule.lookahead_assertion_id, &mut queue);
36 }
37 }
38 visited.into_iter().collect()
39 }
40}
41
42fn collect_refs(grammar: &GrammarData, expr_id: i32, queue: &mut VecDeque<i32>) {
44 let e = grammar.expr(expr_id);
45 match e.kind {
46 GrammarExprType::RuleRef | GrammarExprType::Repeat => queue.push_back(e.data[0]),
47 GrammarExprType::TagDispatch => {
48 for (_, rule_id) in grammar.tag_dispatch(expr_id).tag_rule_pairs {
49 queue.push_back(rule_id);
50 }
51 }
52 GrammarExprType::Sequence | GrammarExprType::Choices => {
53 for &child in e.data {
54 collect_refs(grammar, child, queue);
55 }
56 }
57 _ => {}
58 }
59}
60
61pub struct RuleRefGraphFinder;
64
65impl RuleRefGraphFinder {
66 pub fn apply(grammar: &GrammarData) -> Vec<Vec<i32>> {
68 let num_rules = grammar.num_rules() as usize;
69 let mut graph: Vec<Vec<i32>> = vec![Vec::new(); num_rules];
70 for i in 0..grammar.num_rules() {
71 let body = grammar.rule(i).body_expr_id;
72 visit_refs(grammar, body, i, &mut graph);
73 }
74 for row in &mut graph {
75 row.sort_unstable();
76 row.dedup();
77 }
78 graph
79 }
80}
81
82fn visit_refs(grammar: &GrammarData, expr_id: i32, cur_rule: i32, graph: &mut [Vec<i32>]) {
85 let e = grammar.expr(expr_id);
86 match e.kind {
87 GrammarExprType::RuleRef | GrammarExprType::Repeat => {
88 graph[e.data[0] as usize].push(cur_rule);
89 }
90 GrammarExprType::TagDispatch => {
91 for (_, rule_id) in grammar.tag_dispatch(expr_id).tag_rule_pairs {
92 graph[rule_id as usize].push(cur_rule);
93 }
94 }
95 GrammarExprType::Sequence | GrammarExprType::Choices => {
96 for &child in e.data {
97 visit_refs(grammar, child, cur_rule, graph);
98 }
99 }
100 _ => {}
101 }
102}
103
104pub struct AllowEmptyRuleAnalyzer;
107
108impl AllowEmptyRuleAnalyzer {
109 pub fn apply(grammar: &GrammarData) -> Vec<i32> {
111 let mut empty: HashSet<i32> = HashSet::new();
112 Self::find_explicit(grammar, &mut empty);
113 let graph = RuleRefGraphFinder::apply(grammar);
114 Self::find_indirect(grammar, &mut empty, &graph);
115 let mut result: Vec<i32> = empty.into_iter().collect();
116 result.sort_unstable();
117 result
118 }
119
120 fn find_explicit(grammar: &GrammarData, empty: &mut HashSet<i32>) {
123 for i in 0..grammar.num_rules() {
124 let body_id = grammar.rule(i).body_expr_id;
125 let body = grammar.expr(body_id);
126 if body.kind == GrammarExprType::TagDispatch {
127 if grammar.tag_dispatch(body_id).stop_eos {
128 empty.insert(i);
129 }
130 continue;
131 }
132 debug_assert_eq!(body.kind, GrammarExprType::Choices);
133 if grammar.expr(body.data[0]).kind == GrammarExprType::EmptyStr {
134 empty.insert(i);
135 continue;
136 }
137 for &seq_id in body.data {
138 let seq = grammar.expr(seq_id);
139 if seq.kind == GrammarExprType::Sequence
140 && !seq.data.is_empty()
141 && seq
142 .data
143 .iter()
144 .all(|&x| grammar.expr(x).kind == GrammarExprType::CharacterClassStar)
145 {
146 empty.insert(i);
147 break;
148 }
149 }
150 }
151 }
152
153 fn seq_is_epsilon(grammar: &GrammarData, seq_id: i32, empty: &HashSet<i32>) -> bool {
156 let seq = grammar.expr(seq_id);
157 if seq.kind == GrammarExprType::EmptyStr {
158 return true;
159 }
160 debug_assert_eq!(seq.kind, GrammarExprType::Sequence);
161 seq.data.iter().all(|&x| {
162 let elem = grammar.expr(x);
163 match elem.kind {
164 GrammarExprType::RuleRef => empty.contains(&elem.data[0]),
165 GrammarExprType::CharacterClassStar => true,
166 GrammarExprType::Repeat => empty.contains(&elem.data[0]) || elem.data[1] == 0,
167 _ => false,
168 }
169 })
170 }
171
172 fn find_indirect(grammar: &GrammarData, empty: &mut HashSet<i32>, graph: &[Vec<i32>]) {
174 let mut queue: VecDeque<i32> = empty.iter().copied().collect();
175 while let Some(rule_id) = queue.pop_front() {
176 for &referer in &graph[rule_id as usize] {
177 if empty.contains(&referer) {
178 continue;
179 }
180 let body = grammar.expr(grammar.rule(referer).body_expr_id);
181 debug_assert_ne!(body.kind, GrammarExprType::TagDispatch);
182 let is_epsilon = body
183 .data
184 .iter()
185 .any(|&seq_id| Self::seq_is_epsilon(grammar, seq_id, empty));
186 if is_epsilon {
187 empty.insert(referer);
188 queue.push_back(referer);
189 }
190 }
191 }
192 }
193}
194
195#[cfg(test)]
196#[path = "analyzer_tests.rs"]
197mod tests;