1use bit_matrix::BitMatrix;
4use bit_vec::BitVec;
5
6use crate::derivation;
7use cfg_grammar::rhs_closure::RhsClosure;
8use cfg_grammar::rule::RuleRef;
9use cfg_grammar::symbol::set::SymbolBitSet;
10use cfg_grammar::RuleContainer;
11use cfg_symbol::Symbol;
12
13pub struct Usefulness<G> {
16 grammar: G,
17 reachability: BitMatrix,
18 reachable_syms: BitVec,
19 productivity: BitVec,
20}
21
22pub struct UselessRules<'a, G, I>
24where
25 G: 'a,
26{
27 usefulness: &'a Usefulness<&'a mut G>,
28 rules: I,
29}
30
31#[derive(Clone, Debug)]
33pub struct UselessRule<R> {
34 rule: R,
36 usefulness: RuleUsefulness,
37}
38
39#[derive(Copy, Clone, Debug)]
40pub struct RuleUsefulness {
41 reachable: bool,
43 productive: bool,
45}
46
47impl<R> UselessRule<R> {
48 pub fn rule(&self) -> &R {
49 &self.rule
50 }
51
52 pub fn usefulness(&self) -> &RuleUsefulness {
53 &self.usefulness
54 }
55}
56
57impl RuleUsefulness {
58 fn is_useless(&self) -> bool {
59 !self.reachable || !self.productive
60 }
61}
62
63fn unused_syms<'a, G>(grammar: &'a G) -> BitVec
65where
66 G: RuleContainer,
67{
68 let mut result = used_syms(grammar);
69 result.negate();
70 result
71}
72
73fn used_syms<'a, G>(grammar: &'a G) -> BitVec
75where
76 G: RuleContainer,
77{
78 let num_syms = grammar.sym_source().num_syms();
79 let mut used_syms = BitVec::from_elem(num_syms, false);
80
81 for rule in grammar.rules() {
82 used_syms.set(rule.lhs.usize(), true);
83 for &sym in rule.rhs {
84 used_syms.set(sym.usize(), true);
85 }
86 }
87 used_syms
88}
89
90fn productive_syms<G>(grammar: &G) -> BitVec
92where
93 G: RuleContainer,
94{
95 let mut productive_syms = SymbolBitSet::terminal_or_nulling_set(grammar).into_bit_vec();
96 RhsClosure::new(grammar).rhs_closure(&mut productive_syms);
97 productive_syms
98}
99
100impl<'a, G> Usefulness<&'a mut G>
101where
102 G: RuleContainer,
103{
104 pub fn new(grammar: &'a mut G) -> Usefulness<&'a mut G> {
107 let mut productivity = productive_syms(grammar);
108 let reachability = derivation::reachability_matrix(grammar);
109 let unused_syms = unused_syms(grammar);
110 let mut reachable_syms = BitVec::from_elem(grammar.sym_source().num_syms(), false);
111
112 productivity.or(&unused_syms);
113 reachable_syms.or(&unused_syms);
114
115 debug_assert_eq!(
116 reachability.size(),
117 (productivity.len(), productivity.len())
118 );
119
120 Usefulness {
121 grammar: grammar,
122 productivity: productivity,
123 reachability: reachability,
124 reachable_syms: reachable_syms,
125 }
126 }
127
128 pub fn productivity(&self, sym: Symbol) -> bool {
131 self.productivity[sym.usize()]
132 }
133
134 pub fn reachable<Sr>(mut self, syms: Sr) -> Self
136 where
137 Sr: AsRef<[Symbol]>,
138 {
139 for &sym in syms.as_ref().iter() {
140 let reachability =
141 self.reachability[sym.usize()].iter_bits(self.grammar.sym_source().num_syms());
142 for (i, is_reachable) in reachability.enumerate() {
143 if is_reachable {
144 self.reachable_syms.set(i, true);
145 }
146 }
147 }
148 self
149 }
150
151 pub fn all_useful(&self) -> bool {
153 self.productivity.all() && self.reachable_syms.all()
154 }
155
156 pub fn all_productive(&self) -> bool {
158 self.productivity.all()
159 }
160
161 pub fn all_reachable(&self) -> bool {
163 self.reachable_syms.all()
164 }
165
166 pub fn rule_usefulness(&self, rule: RuleRef) -> RuleUsefulness {
167 let productive = rule.rhs.iter().all(|sym| self.productivity[sym.usize()]);
168 let reachable = self.reachable_syms[rule.lhs.usize()];
169 RuleUsefulness {
170 productive,
171 reachable,
172 }
173 }
174
175 pub fn useless_rules(&'a self) -> UselessRules<'a, G, impl Iterator<Item = RuleRef<'a>>> {
177 UselessRules {
178 rules: self.grammar.rules(),
179 usefulness: self,
180 }
181 }
182}
183
184impl<'a, G> Usefulness<&'a mut G>
186where
187 G: RuleContainer,
188{
189 pub fn remove_useless_rules(&mut self) {
191 if !self.all_useful() {
192 let productivity = &self.productivity;
193 let reachable_syms = &self.reachable_syms;
194 let rule_is_useful = |rule: RuleRef| {
195 let productive = rule.rhs.iter().all(|sym| productivity[sym.usize()]);
196 let reachable = reachable_syms[rule.lhs.usize()];
197 productive && reachable
198 };
199 self.grammar.retain(rule_is_useful);
200 }
201 }
202}
203
204impl<'a, G, I> Iterator for UselessRules<'a, G, I>
205where
206 G: RuleContainer,
207 I: Iterator<Item = RuleRef<'a>>,
208{
209 type Item = UselessRule<I::Item>;
210
211 fn next(&mut self) -> Option<Self::Item> {
212 if self.usefulness.all_useful() {
213 return None;
214 }
215
216 for rule in &mut self.rules {
217 let usefulness = self.usefulness.rule_usefulness(rule);
218
219 if usefulness.is_useless() {
220 return Some(UselessRule { rule, usefulness });
221 }
222 }
223
224 None
225 }
226}