rustc_transmute/layout/
dfa.rs
1use std::fmt;
2use std::sync::atomic::{AtomicU32, Ordering};
3
4use tracing::instrument;
5
6use super::{Byte, Nfa, Ref, nfa};
7use crate::Map;
8
9#[derive(PartialEq, Clone, Debug)]
10pub(crate) struct Dfa<R>
11where
12 R: Ref,
13{
14 pub(crate) transitions: Map<State, Transitions<R>>,
15 pub(crate) start: State,
16 pub(crate) accepting: State,
17}
18
19#[derive(PartialEq, Clone, Debug)]
20pub(crate) struct Transitions<R>
21where
22 R: Ref,
23{
24 byte_transitions: Map<Byte, State>,
25 ref_transitions: Map<R, State>,
26}
27
28impl<R> Default for Transitions<R>
29where
30 R: Ref,
31{
32 fn default() -> Self {
33 Self { byte_transitions: Map::default(), ref_transitions: Map::default() }
34 }
35}
36
37impl<R> Transitions<R>
38where
39 R: Ref,
40{
41 #[cfg(test)]
42 fn insert(&mut self, transition: Transition<R>, state: State) {
43 match transition {
44 Transition::Byte(b) => {
45 self.byte_transitions.insert(b, state);
46 }
47 Transition::Ref(r) => {
48 self.ref_transitions.insert(r, state);
49 }
50 }
51 }
52}
53
54#[derive(Hash, Eq, PartialEq, PartialOrd, Ord, Copy, Clone)]
56pub(crate) struct State(u32);
57
58#[cfg(test)]
59#[derive(Hash, Eq, PartialEq, Clone, Copy)]
60pub(crate) enum Transition<R>
61where
62 R: Ref,
63{
64 Byte(Byte),
65 Ref(R),
66}
67
68impl fmt::Debug for State {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "S_{}", self.0)
71 }
72}
73
74#[cfg(test)]
75impl<R> fmt::Debug for Transition<R>
76where
77 R: Ref,
78{
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 match &self {
81 Self::Byte(b) => b.fmt(f),
82 Self::Ref(r) => r.fmt(f),
83 }
84 }
85}
86
87impl<R> Dfa<R>
88where
89 R: Ref,
90{
91 #[cfg(test)]
92 pub(crate) fn bool() -> Self {
93 let mut transitions: Map<State, Transitions<R>> = Map::default();
94 let start = State::new();
95 let accepting = State::new();
96
97 transitions.entry(start).or_default().insert(Transition::Byte(Byte::Init(0x00)), accepting);
98
99 transitions.entry(start).or_default().insert(Transition::Byte(Byte::Init(0x01)), accepting);
100
101 Self { transitions, start, accepting }
102 }
103
104 #[instrument(level = "debug")]
105 pub(crate) fn from_nfa(nfa: Nfa<R>) -> Self {
106 let Nfa { transitions: nfa_transitions, start: nfa_start, accepting: nfa_accepting } = nfa;
107
108 let mut dfa_transitions: Map<State, Transitions<R>> = Map::default();
109 let mut nfa_to_dfa: Map<nfa::State, State> = Map::default();
110 let dfa_start = State::new();
111 nfa_to_dfa.insert(nfa_start, dfa_start);
112
113 let mut queue = vec![(nfa_start, dfa_start)];
114
115 while let Some((nfa_state, dfa_state)) = queue.pop() {
116 if nfa_state == nfa_accepting {
117 continue;
118 }
119
120 for (nfa_transition, next_nfa_states) in nfa_transitions[&nfa_state].iter() {
121 let dfa_transitions =
122 dfa_transitions.entry(dfa_state).or_insert_with(Default::default);
123
124 let mapped_state = next_nfa_states.iter().find_map(|x| nfa_to_dfa.get(x).copied());
125
126 let next_dfa_state = match nfa_transition {
127 &nfa::Transition::Byte(b) => *dfa_transitions
128 .byte_transitions
129 .entry(b)
130 .or_insert_with(|| mapped_state.unwrap_or_else(State::new)),
131 &nfa::Transition::Ref(r) => *dfa_transitions
132 .ref_transitions
133 .entry(r)
134 .or_insert_with(|| mapped_state.unwrap_or_else(State::new)),
135 };
136
137 for &next_nfa_state in next_nfa_states {
138 nfa_to_dfa.entry(next_nfa_state).or_insert_with(|| {
139 queue.push((next_nfa_state, next_dfa_state));
140 next_dfa_state
141 });
142 }
143 }
144 }
145
146 let dfa_accepting = nfa_to_dfa[&nfa_accepting];
147
148 Self { transitions: dfa_transitions, start: dfa_start, accepting: dfa_accepting }
149 }
150
151 pub(crate) fn bytes_from(&self, start: State) -> Option<&Map<Byte, State>> {
152 Some(&self.transitions.get(&start)?.byte_transitions)
153 }
154
155 pub(crate) fn byte_from(&self, start: State, byte: Byte) -> Option<State> {
156 self.transitions.get(&start)?.byte_transitions.get(&byte).copied()
157 }
158
159 pub(crate) fn refs_from(&self, start: State) -> Option<&Map<R, State>> {
160 Some(&self.transitions.get(&start)?.ref_transitions)
161 }
162}
163
164impl State {
165 pub(crate) fn new() -> Self {
166 static COUNTER: AtomicU32 = AtomicU32::new(0);
167 Self(COUNTER.fetch_add(1, Ordering::SeqCst))
168 }
169}
170
171#[cfg(test)]
172impl<R> From<nfa::Transition<R>> for Transition<R>
173where
174 R: Ref,
175{
176 fn from(nfa_transition: nfa::Transition<R>) -> Self {
177 match nfa_transition {
178 nfa::Transition::Byte(byte) => Transition::Byte(byte),
179 nfa::Transition::Ref(r) => Transition::Ref(r),
180 }
181 }
182}