cfg_symbol_bit_matrix/
symbol_bit_matrix.rs1use std::ops::{self, Deref, DerefMut};
2
3use bit_matrix::BitMatrix;
4
5use cfg_grammar::Cfg;
6use cfg_symbol::{Symbol, SymbolSource};
7
8#[derive(Debug)]
10pub struct SymbolBitMatrix {
11 bit_matrix: BitMatrix,
12}
13
14pub struct DirectDerivationMatrix(SymbolBitMatrix);
16pub struct ReachabilityMatrix(SymbolBitMatrix);
18pub struct UnitDerivationMatrix(SymbolBitMatrix);
20
21impl SymbolBitMatrix {
22 fn new(num_syms: usize) -> Self {
23 SymbolBitMatrix {
24 bit_matrix: BitMatrix::new(num_syms, num_syms),
25 }
26 }
27
28 fn set(&mut self, row: Symbol, col: Symbol, included: bool) {
29 self.bit_matrix.set(row.usize(), col.usize(), included);
30 }
31
32 pub fn iter_row_syms(&self, row: Symbol) -> impl Iterator<Item = Symbol> + '_ {
34 self.bit_matrix
35 .iter_row(row.usize())
36 .zip(SymbolSource::generate_fresh())
37 .filter_map(|(present, sym)| if present { Some(sym) } else { None })
38 }
39}
40
41impl Deref for SymbolBitMatrix {
42 type Target = BitMatrix;
43 fn deref(&self) -> &Self::Target {
44 &self.bit_matrix
45 }
46}
47
48impl DerefMut for SymbolBitMatrix {
49 fn deref_mut(&mut self) -> &mut Self::Target {
50 &mut self.bit_matrix
51 }
52}
53
54impl Deref for DirectDerivationMatrix {
55 type Target = SymbolBitMatrix;
56 fn deref(&self) -> &Self::Target {
57 &self.0
58 }
59}
60
61impl DerefMut for DirectDerivationMatrix {
62 fn deref_mut(&mut self) -> &mut Self::Target {
63 &mut self.0
64 }
65}
66
67impl Deref for ReachabilityMatrix {
68 type Target = SymbolBitMatrix;
69 fn deref(&self) -> &Self::Target {
70 &self.0
71 }
72}
73
74impl DerefMut for ReachabilityMatrix {
75 fn deref_mut(&mut self) -> &mut Self::Target {
76 &mut self.0
77 }
78}
79
80impl Deref for UnitDerivationMatrix {
81 type Target = SymbolBitMatrix;
82 fn deref(&self) -> &Self::Target {
83 &self.0
84 }
85}
86
87impl DerefMut for UnitDerivationMatrix {
88 fn deref_mut(&mut self) -> &mut Self::Target {
89 &mut self.0
90 }
91}
92
93impl From<DirectDerivationMatrix> for SymbolBitMatrix {
94 fn from(value: DirectDerivationMatrix) -> Self {
95 value.0
96 }
97}
98
99impl From<ReachabilityMatrix> for SymbolBitMatrix {
100 fn from(value: ReachabilityMatrix) -> Self {
101 value.0
102 }
103}
104
105impl From<UnitDerivationMatrix> for SymbolBitMatrix {
106 fn from(value: UnitDerivationMatrix) -> Self {
107 value.0
108 }
109}
110
111static TRUE: bool = true;
112static FALSE: bool = false;
113
114impl ops::Index<(Symbol, Symbol)> for SymbolBitMatrix {
115 type Output = bool;
116 fn index(&self, index: (Symbol, Symbol)) -> &Self::Output {
117 if self.bit_matrix[(index.0.usize(), index.1.usize())] {
118 &TRUE
119 } else {
120 &FALSE
121 }
122 }
123}
124
125impl TryFrom<BitMatrix> for SymbolBitMatrix {
126 type Error = ();
127
128 fn try_from(bit_matrix: BitMatrix) -> Result<Self, Self::Error> {
129 let (rows, cols) = bit_matrix.size();
130 if rows == cols {
131 Ok(SymbolBitMatrix { bit_matrix })
132 } else {
133 Err(())
134 }
135 }
136}
137
138impl From<SymbolBitMatrix> for BitMatrix {
139 fn from(value: SymbolBitMatrix) -> Self {
140 value.bit_matrix
141 }
142}
143
144impl ReachabilityMatrix {
145 pub fn reflexive(mut self) -> Self {
147 self.reflexive_closure();
148 self
149 }
150}
151
152impl DirectDerivationMatrix {
153 pub fn reachability(mut self) -> ReachabilityMatrix {
155 self.transitive_closure();
156 ReachabilityMatrix(self.into())
157 }
158}
159
160pub trait CfgSymbolBitMatrixExt {
163 fn empty_matrix(&self) -> SymbolBitMatrix;
165 fn direct_derivation_matrix(&self) -> DirectDerivationMatrix;
167 fn reachability_matrix(&self) -> ReachabilityMatrix;
169 fn unit_derivation_matrix(&self) -> UnitDerivationMatrix;
176}
177
178impl CfgSymbolBitMatrixExt for Cfg {
179 fn empty_matrix(&self) -> SymbolBitMatrix {
180 SymbolBitMatrix::new(self.num_syms())
181 }
182
183 fn direct_derivation_matrix(&self) -> DirectDerivationMatrix {
184 let mut derivation = self.empty_matrix();
185
186 for rule in self.rules() {
187 for &sym in rule.rhs.iter() {
188 derivation.set(rule.lhs, sym, true);
189 }
190 }
191
192 DirectDerivationMatrix(derivation)
193 }
194
195 fn reachability_matrix(&self) -> ReachabilityMatrix {
196 self.direct_derivation_matrix().reachability()
197 }
198
199 fn unit_derivation_matrix(&self) -> UnitDerivationMatrix {
200 let mut unit_derivation = self.empty_matrix();
201
202 for rule in self.rules() {
203 if rule.rhs.len() == 1 && rule.lhs != rule.rhs[0] {
207 unit_derivation.set(rule.lhs, rule.rhs[0], true);
208 }
209 }
210
211 unit_derivation.transitive_closure();
212 UnitDerivationMatrix(unit_derivation)
213 }
214}