metrale_grammar/fsm/
dfa_ops.rs1use ahash::{AHashMap, AHashSet};
9use std::collections::VecDeque;
10
11use super::algorithms::DEFAULT_MAX_STATES;
12use super::fsm::Fsm;
13use super::with_start_end::FsmWithStartEnd;
14
15impl FsmWithStartEnd {
16 pub fn minimize_dfa(&self, max_num_states: usize) -> Result<FsmWithStartEnd, String> {
18 if self.num_states() > max_num_states {
19 return Err("The number of states exceeds the limit.".to_string());
20 }
21 let now_fsm = if self.is_dfa {
22 self.copy()
23 } else {
24 self.to_dfa(max_num_states)?
25 };
26 let n = now_fsm.num_states();
27
28 let mut precursors: Vec<Vec<((i16, i16), usize)>> = vec![Vec::new(); n];
30 for i in 0..n {
31 for edge in now_fsm.fsm().edges(i) {
32 precursors[edge.target as usize].push(((edge.min, edge.max), i));
33 }
34 }
35
36 let mut final_states: AHashSet<i32> = AHashSet::new();
37 let mut non_final: AHashSet<i32> = AHashSet::new();
38 for i in 0..n {
39 if now_fsm.is_end_state(i) {
40 final_states.insert(i as i32);
41 } else {
42 non_final.insert(i as i32);
43 }
44 }
45 let mut partitions: Vec<AHashSet<i32>> = vec![final_states.clone(), non_final.clone()];
46 let mut working: Vec<AHashSet<i32>> = vec![final_states, non_final];
47
48 while let Some(current) = working.pop() {
49 let mut possible: AHashMap<(i16, i16), AHashSet<i32>> = AHashMap::new();
51 for &state in ¤t {
52 for &(label, src) in &precursors[state as usize] {
53 possible.entry(label).or_default().insert(src as i32);
54 }
55 }
56 for (_label, precs) in possible {
57 let mut i = 0;
58 while i < partitions.len() {
59 let intersection: Vec<i32> = partitions[i]
60 .iter()
61 .copied()
62 .filter(|s| precs.contains(s))
63 .collect();
64 let difference: Vec<i32> = partitions[i]
65 .iter()
66 .copied()
67 .filter(|s| !precs.contains(s))
68 .collect();
69 if !intersection.is_empty() && !difference.is_empty() {
70 let part = partitions[i].clone();
71 let in_working = working.iter().position(|w| *w == part);
72 match in_working {
73 Some(wi) => {
74 working[wi] = intersection.iter().copied().collect();
75 working.push(difference.iter().copied().collect());
76 }
77 None => {
78 let smaller = if difference.len() < intersection.len() {
79 &difference
80 } else {
81 &intersection
82 };
83 working.push(smaller.iter().copied().collect());
84 }
85 }
86 partitions[i] = intersection.iter().copied().collect();
87 partitions.push(difference.iter().copied().collect());
88 }
89 i += 1;
90 }
91 }
92 }
93
94 let mut state_mapping = vec![0usize; n];
95 for (i, part) in partitions.iter().enumerate() {
96 for &state in part {
97 state_mapping[state as usize] = i;
98 }
99 }
100 Ok(now_fsm.rebuild_with_mapping(&state_mapping, partitions.len()))
101 }
102
103 pub fn not(&self, max_result_num_states: usize) -> Result<FsmWithStartEnd, String> {
106 if !self.is_leaf() {
107 return Err("Not operation is not supported for FSM with rule references.".to_string());
108 }
109 let mut result = if self.is_dfa {
110 self.copy()
111 } else {
112 self.to_dfa(max_result_num_states)?
113 };
114
115 let mut new_final = vec![false; result.num_states() + 1];
116 for i in 0..result.num_states() {
117 if !result.is_end_state(i) {
118 new_final[i] = true;
119 }
120 }
121 let accept_all = result.add_state();
122 new_final[accept_all] = true;
123
124 for i in 0..result.num_states() {
125 if i == accept_all {
126 continue;
127 }
128 let mut char_set = [false; 256];
129 for edge in result.fsm().edges(i) {
130 if edge.is_char_range() {
131 for c in edge.min..=edge.max {
132 char_set[c as usize] = true;
133 }
134 }
135 }
136 let mut left = 0usize;
137 while left < 256 {
138 if char_set[left] {
139 left += 1;
140 continue;
141 }
142 let mut right = left + 1;
143 while right < 256 && !char_set[right] {
144 right += 1;
145 }
146 result
147 .fsm_mut()
148 .add_edge(i, accept_all, left as i16, (right - 1) as i16);
149 left = right;
150 }
151 }
152 result.set_end_states(new_final);
153 Ok(result)
154 }
155
156 pub fn intersect(
158 lhs: &FsmWithStartEnd,
159 rhs: &FsmWithStartEnd,
160 _max_result_num_states: usize,
161 ) -> Result<FsmWithStartEnd, String> {
162 if !lhs.is_leaf() || !rhs.is_leaf() {
163 return Err("Intersect only support leaf fsm!".to_string());
164 }
165 let lhs_dfa = lhs.to_dfa(DEFAULT_MAX_STATES)?;
166 let rhs_dfa = rhs.to_dfa(DEFAULT_MAX_STATES)?;
167
168 let mut result = FsmWithStartEnd::new(Fsm::with_states(0), 0, Vec::new(), true);
169 let mut state_map: AHashMap<(usize, usize), usize> = AHashMap::new();
170 let mut queue: VecDeque<(usize, usize)> = VecDeque::new();
171
172 queue.push_back((lhs_dfa.start(), rhs_dfa.start()));
173 result.add_state();
174 state_map.insert((lhs_dfa.start(), rhs_dfa.start()), 0);
175
176 while let Some((ls, rs)) = queue.pop_front() {
177 if lhs_dfa.is_end_state(ls) && rhs_dfa.is_end_state(rs) {
178 let id = state_map[&(ls, rs)];
179 result.add_end_state(id);
180 }
181 for le in lhs_dfa.fsm().edges(ls) {
182 for re in rhs_dfa.fsm().edges(rs) {
183 if !le.is_char_range() || !re.is_char_range() {
184 continue;
185 }
186 if le.min > re.max || re.min > le.max {
187 continue;
188 }
189 let min_v = le.min.max(re.min);
190 let max_v = le.max.min(re.max);
191 let key = (le.target as usize, re.target as usize);
192 let target = match state_map.get(&key) {
193 Some(&t) => t,
194 None => {
195 let t = result.add_state();
196 state_map.insert(key, t);
197 queue.push_back(key);
198 t
199 }
200 };
201 let src = state_map[&(ls, rs)];
202 result.fsm_mut().add_edge(src, target, min_v, max_v);
203 }
204 }
205 }
206 Ok(result)
207 }
208}