use core::fmt; use std::collections::HashMap; use super::{ byte_range::ByteRange, enfa::{ENFA, MultiState}, }; pub type StateId = usize; pub struct State { trans: HashMap, default_trans: StateId, accept: bool, } pub struct DFA { start: StateId, states: Vec, } impl fmt::Debug for DFA { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "DFA {{")?; for (i, s) in self.states.iter().enumerate() { if self.start == i { write!(f, "-> {i}: ")?; } else { write!(f, " {i}: ")?; } for (chr, to) in s.trans.iter() { write!(f, "{chr:?} to {to}, ")?; } write!(f, "default to {}", s.default_trans)?; if s.accept { write!(f, ", accept")?; } writeln!(f)?; } writeln!(f, "}}") } } impl DFA { pub fn matches(&self, x: &[u8]) -> bool { let mut state = self.start; 'next_byte: for &b in x.iter() { for (range, &next_state) in self.states[state].trans.iter() { if range.contains(b) { state = next_state; continue 'next_byte; } } state = self.states[state].default_trans; } self.states[state].accept } } impl From for DFA { fn from(mut nfa: ENFA) -> Self { nfa.simplify(); for s in nfa.states.iter() { if !s.epsilon_trans.is_empty() { panic!( "NFA simplification did not remove epsilon transitions - cannot proceed with powerset construction." ); } } let mut multi_states = nfa.all_multi_states(); multi_states.insert(nfa.void_multi_state()); let mut len = 0; let multi_to_dfa: HashMap = multi_states .clone() .into_iter() .map(|ms| { len += 1; (ms, len - 1) }) .collect(); let void = multi_to_dfa[&nfa.void_multi_state()]; let mut states: Vec = (0..len) .map(|_| State { trans: HashMap::new(), default_trans: void, accept: false, }) .collect(); for ms in multi_states.iter() { let i: usize = multi_to_dfa[&ms]; states[i].accept = ms.accept(); for t in ms.possible_transitions() { let k = multi_to_dfa[&ms.transition(t)]; states[i].trans.insert(t, k); } } Self { start: multi_to_dfa[&nfa.start_multi_state()], states, } } }