metrale_grammar/fsm/
with_start_end.rs1use ahash::AHashSet;
13
14use super::edge::edge_type;
15use super::fsm::Fsm;
16
17#[derive(Debug, Clone, Default, PartialEq, Eq)]
19pub struct FsmWithStartEnd {
20 pub(crate) fsm: Fsm,
21 pub(crate) start: usize,
22 pub(crate) ends: Vec<bool>,
24 pub(crate) is_dfa: bool,
26}
27
28impl FsmWithStartEnd {
29 pub fn new(fsm: Fsm, start: usize, ends: Vec<bool>, is_dfa: bool) -> Self {
31 Self {
32 fsm,
33 start,
34 ends,
35 is_dfa,
36 }
37 }
38
39 pub fn fsm(&self) -> &Fsm {
43 &self.fsm
44 }
45
46 pub fn fsm_mut(&mut self) -> &mut Fsm {
48 &mut self.fsm
49 }
50
51 pub fn start(&self) -> usize {
53 self.start
54 }
55
56 pub fn ends(&self) -> &[bool] {
58 &self.ends
59 }
60
61 pub fn is_end_state(&self, state: usize) -> bool {
63 self.ends[state]
64 }
65
66 pub fn num_states(&self) -> usize {
68 self.fsm.num_states()
69 }
70
71 pub fn set_start_state(&mut self, state: usize) {
73 debug_assert!(state < self.num_states());
74 self.start = state;
75 }
76
77 pub fn add_end_state(&mut self, state: usize) {
79 debug_assert!(state < self.num_states());
80 self.ends[state] = true;
81 }
82
83 pub fn set_end_states(&mut self, ends: Vec<bool>) {
85 self.ends = ends;
86 }
87
88 pub fn add_state(&mut self) -> usize {
90 self.ends.push(false);
91 self.fsm.add_state()
92 }
93
94 pub fn is_scanable_state(&self, state: usize) -> bool {
96 self.fsm.edges(state).iter().any(|e| e.is_char_range())
97 }
98
99 pub fn is_non_terminal_state(&self, state: usize) -> bool {
101 self.fsm
102 .edges(state)
103 .iter()
104 .any(|e| e.is_rule_ref() || e.is_epsilon() || e.is_repeat_ref())
105 }
106
107 pub fn accept_string(&self, bytes: &[u8]) -> bool {
111 let mut start_states: AHashSet<i32> = AHashSet::from_iter([self.start as i32]);
112 self.fsm.epsilon_closure(&mut start_states);
113 let mut result_states = AHashSet::new();
114 for &byte in bytes {
115 result_states.clear();
116 self.fsm.advance(
117 &start_states,
118 byte as i32,
119 &mut result_states,
120 edge_type::CHAR_RANGE,
121 false,
122 );
123 if result_states.is_empty() {
124 return false;
125 }
126 std::mem::swap(&mut start_states, &mut result_states);
127 }
128 start_states.iter().any(|&s| self.ends[s as usize])
129 }
130
131 pub fn reachable_states(&self, result: &mut AHashSet<i32>) {
133 self.fsm.reachable_states(&[self.start as i32], result);
134 }
135
136 pub fn is_leaf(&self) -> bool {
138 let mut reachable = AHashSet::new();
139 self.reachable_states(&mut reachable);
140 for &s in &reachable {
141 for edge in self.fsm.edges(s as usize) {
142 if edge.is_rule_ref() || edge.is_repeat_ref() {
143 return false;
144 }
145 }
146 }
147 true
148 }
149
150 pub fn copy(&self) -> FsmWithStartEnd {
154 self.clone()
155 }
156
157 pub fn rebuild_with_mapping(
159 &self,
160 state_mapping: &[usize],
161 new_num_states: usize,
162 ) -> FsmWithStartEnd {
163 let new_fsm = self.fsm.rebuild_with_mapping(state_mapping, new_num_states);
164 let new_start = state_mapping[self.start];
165 let mut new_ends = vec![false; new_num_states];
166 for end in 0..self.num_states() {
167 if self.is_end_state(end) {
168 new_ends[state_mapping[end]] = true;
169 }
170 }
171 FsmWithStartEnd::new(new_fsm, new_start, new_ends, false)
172 }
173
174 pub fn add_to_complete_fsm(&self, complete_fsm: &mut Fsm) -> FsmWithStartEnd {
176 let state_mapping = complete_fsm.add_fsm(&self.fsm);
177 let new_start = state_mapping[self.start];
178 let mut new_ends = vec![false; complete_fsm.num_states()];
179 for end in 0..self.num_states() {
180 if self.is_end_state(end) {
181 new_ends[state_mapping[end]] = true;
182 }
183 }
184 FsmWithStartEnd::new(complete_fsm.clone(), new_start, new_ends, self.is_dfa)
185 }
186
187 pub fn to_compact(&self) -> CompactFsmWithStartEnd {
189 CompactFsmWithStartEnd::new(self.fsm.to_compact(), self.start, self.ends.clone())
190 }
191}
192
193pub use super::compact_with_start_end::CompactFsmWithStartEnd;
196
197#[cfg(test)]
198#[path = "with_start_end_tests.rs"]
199mod tests;