Skip to content

Commit eece122

Browse files
author
Robert Durfee
committed
nfa to dfa
1 parent 5aacea4 commit eece122

File tree

3 files changed

+212
-47
lines changed

3 files changed

+212
-47
lines changed

src/dfa.rs

+169-21
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,57 @@
1-
use std::collections::{HashMap, HashSet};
2-
use std::hash::Hash;
1+
use std::collections::{BTreeMap, BTreeSet};
32

43
use crate::nfa::NFA;
54

5+
#[derive(Debug, PartialEq)]
66
pub(crate) struct DFA<S, E> {
77
initial: S,
8-
transitions: HashMap<S, HashMap<E, S>>,
9-
finals: HashSet<S>,
8+
transitions: BTreeMap<S, BTreeMap<E, S>>,
9+
finals: BTreeSet<S>,
1010
}
1111

1212
impl<S, E> DFA<S, E>
1313
where
14-
S: Copy + Eq + Hash,
15-
E: Copy + Eq + Hash
14+
S: Copy + Ord,
15+
E: Copy + Ord
1616
{
1717
fn new(initial: S) -> Self {
1818
Self {
1919
initial,
20-
transitions: map![initial => HashMap::new()],
21-
finals: HashSet::new(),
20+
transitions: map![initial => BTreeMap::new()],
21+
finals: BTreeSet::new(),
2222
}
2323
}
2424

2525
fn insert(&mut self, state: S) {
2626
if !self.transitions.contains_key(&state) {
27-
self.transitions.insert(state, HashMap::new());
27+
self.transitions.insert(state, BTreeMap::new());
2828
}
2929
}
3030

3131
fn insert_transition(&mut self, start: S, event: E, end: S) {
3232
if !self.transitions.contains_key(&start) {
33-
self.transitions.insert(start, HashMap::new());
33+
self.transitions.insert(start, BTreeMap::new());
3434
}
3535
if !self.transitions.contains_key(&end) {
36-
self.transitions.insert(end, HashMap::new());
36+
self.transitions.insert(end, BTreeMap::new());
3737
}
3838
self.transitions.get_mut(&start).unwrap().insert(event, end);
3939
}
4040

4141
fn insert_final(&mut self, state: S) {
4242
if !self.transitions.contains_key(&state) {
43-
self.transitions.insert(state, HashMap::new());
43+
self.transitions.insert(state, BTreeMap::new());
4444
}
4545
self.finals.insert(state);
4646
}
4747
}
4848

49-
impl<S, E> Extend<(S, HashMap<E, S>)> for DFA<S, E>
49+
impl<S, E> Extend<(S, BTreeMap<E, S>)> for DFA<S, E>
5050
where
51-
S: Copy + Eq + Hash,
52-
E: Copy + Eq + Hash
51+
S: Copy + Ord,
52+
E: Copy + Ord
5353
{
54-
fn extend<T: IntoIterator<Item = (S, HashMap<E, S>)>>(&mut self, iter: T) {
54+
fn extend<T: IntoIterator<Item = (S, BTreeMap<E, S>)>>(&mut self, iter: T) {
5555
for (start, transitions) in iter.into_iter() {
5656
for (event, end) in transitions.into_iter() {
5757
self.insert_transition(start, event, end);
@@ -60,12 +60,160 @@ where
6060
}
6161
}
6262

63-
impl<S, E> From<NFA<S, E>> for DFA<S, E>
63+
impl<S, E> From<NFA<S, E>> for DFA<BTreeSet<S>, E>
6464
where
65-
S: Eq + Hash,
66-
E: Eq + Hash
65+
S: Clone + Ord,
66+
E: Clone + Ord
6767
{
68-
fn from(_nfa: NFA<S, E>) -> DFA<S, E> {
69-
panic!("Not implemented")
68+
fn from(nfa: NFA<S, E>) -> DFA<BTreeSet<S>, E> {
69+
let mut start_sets = vec![set![nfa.initial().clone()]];
70+
let mut transitions = BTreeMap::new();
71+
let mut finals = BTreeSet::new();
72+
while let Some(start_set) = start_sets.pop() {
73+
transitions.insert(start_set.clone(), BTreeMap::new());
74+
for start in &start_set {
75+
for (event, end_set) in nfa.get(&start).unwrap().clone() {
76+
if !transitions.contains_key(&end_set) {
77+
start_sets.push(end_set.clone());
78+
}
79+
transitions.get_mut(&start_set).unwrap().insert(event, end_set);
80+
}
81+
if nfa.is_final(&start) {
82+
finals.insert(start_set.clone());
83+
}
84+
}
85+
}
86+
DFA {
87+
initial: set![nfa.initial().clone()],
88+
transitions,
89+
finals
90+
}
91+
}
92+
}
93+
94+
#[cfg(test)]
95+
mod tests {
96+
use crate::nfa::ENFA;
97+
use crate::dfa::DFA;
98+
use crate::re::RE;
99+
100+
#[test]
101+
fn test_1() {
102+
let expected = DFA {
103+
initial: set![0u128],
104+
transitions: map![
105+
set![0u128] => map![
106+
None => set![1u128]
107+
],
108+
set![1u128] => map![]
109+
],
110+
finals: set![set![1u128]],
111+
};
112+
let actual = DFA::from(ENFA::from(RE::Epsilon));
113+
assert_eq!(expected, actual);
114+
}
115+
116+
#[test]
117+
fn test_2() {
118+
let expected = DFA {
119+
initial: set![0u128],
120+
transitions: map![
121+
set![0u128] => map![
122+
Some('A') => set![1u128]
123+
],
124+
set![1u128] => map![]
125+
],
126+
finals: set![set![1u128]],
127+
};
128+
let actual = DFA::from(ENFA::from(RE::Symbol { symbol: 'A' }));
129+
assert_eq!(expected, actual);
130+
}
131+
132+
#[test]
133+
fn test_3() {
134+
let expected = DFA {
135+
initial: set![0u128],
136+
transitions: map![
137+
set![0u128] => map![
138+
None => set![2u128, 4u128]
139+
],
140+
set![2u128, 4u128] => map![
141+
None => set![3u128],
142+
Some('A') => set![5u128]
143+
],
144+
set![3u128] => map![
145+
None => set![1u128]
146+
],
147+
set![5u128] => map![
148+
None => set![1u128]
149+
],
150+
set![1u128] => map![]
151+
],
152+
finals: set![set![1u128]],
153+
};
154+
let actual = DFA::from(ENFA::from(RE::Alternation {
155+
res: vec![
156+
RE::Epsilon,
157+
RE::Symbol { symbol: 'A' },
158+
],
159+
}));
160+
assert_eq!(expected, actual);
161+
}
162+
163+
#[test]
164+
fn test_4() {
165+
let expected = DFA {
166+
initial: set![0u128],
167+
transitions: map![
168+
set![0u128] => map![
169+
None => set![2u128]
170+
],
171+
set![2u128] => map![
172+
Some('A') => set![3u128]
173+
],
174+
set![3u128] => map![
175+
None => set![4u128]
176+
],
177+
set![4u128] => map![
178+
None => set![5u128]
179+
],
180+
set![5u128] => map![
181+
None => set![1u128]
182+
],
183+
set![1u128] => map![]
184+
],
185+
finals: set![set![1u128]],
186+
};
187+
let actual = DFA::from(ENFA::from(RE::Concatenation {
188+
res: vec![
189+
RE::Symbol { symbol: 'A' },
190+
RE::Epsilon,
191+
],
192+
}));
193+
assert_eq!(expected, actual);
194+
}
195+
196+
#[test]
197+
fn test_5() {
198+
let expected = DFA {
199+
initial: set![0u128],
200+
transitions: map![
201+
set![0u128] => map![
202+
None => set![2u128, 1u128]
203+
],
204+
set![2u128, 1u128] => map![
205+
Some('A') => set![3u128]
206+
],
207+
set![3u128] => map![
208+
None => set![2u128, 1u128]
209+
]
210+
],
211+
finals: set![set![2u128, 1u128]],
212+
};
213+
let actual = DFA::from(ENFA::from(RE::Repetition {
214+
re: Box::new(RE::Symbol { symbol: 'A' }),
215+
}));
216+
assert_eq!(expected, actual);
70217
}
218+
71219
}

src/nfa.rs

+37-20
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,84 @@
1-
use std::collections::{HashMap, HashSet};
2-
use std::hash::Hash;
1+
use std::collections::{BTreeMap, BTreeSet};
32

43
use crate::util::IDGenerator;
54
use crate::re::RE;
65

76
#[derive(Debug, PartialEq)]
87
pub(crate) struct NFA<S, E>
98
where
10-
S: Eq + Hash,
11-
E: Eq + Hash
9+
S: Ord,
10+
E: Ord
1211
{
1312
initial: S,
14-
transitions: HashMap<S, HashMap<E, HashSet<S>>>,
15-
finals: HashSet<S>,
13+
transitions: BTreeMap<S, BTreeMap<E, BTreeSet<S>>>,
14+
finals: BTreeSet<S>,
1615
}
1716

1817
impl<S, E> NFA<S, E>
1918
where
20-
S: Copy + Eq + Hash,
21-
E: Copy + Eq + Hash
19+
S: Copy + Ord,
20+
E: Copy + Ord
2221
{
2322
fn new(initial: S) -> Self {
2423
Self {
2524
initial,
26-
transitions: map![initial => HashMap::new()],
27-
finals: HashSet::new(),
25+
transitions: map![initial => BTreeMap::new()],
26+
finals: BTreeSet::new(),
2827
}
2928
}
3029

3130
fn insert(&mut self, state: S) {
3231
if !self.transitions.contains_key(&state) {
33-
self.transitions.insert(state, HashMap::new());
32+
self.transitions.insert(state, BTreeMap::new());
3433
}
3534
}
3635

3736
fn insert_transition(&mut self, start: S, event: E, end: S) {
3837
if !self.transitions.contains_key(&start) {
39-
self.transitions.insert(start, HashMap::new());
38+
self.transitions.insert(start, BTreeMap::new());
4039
}
4140
if !self.transitions.contains_key(&end) {
42-
self.transitions.insert(end, HashMap::new());
41+
self.transitions.insert(end, BTreeMap::new());
4342
}
4443
let start_transitions = self.transitions.get_mut(&start).unwrap();
4544
if !start_transitions.contains_key(&event) {
46-
start_transitions.insert(event, HashSet::new());
45+
start_transitions.insert(event, BTreeSet::new());
4746
}
4847
start_transitions.get_mut(&event).unwrap().insert(end);
4948
}
5049

5150
fn insert_final(&mut self, state: S) {
5251
if !self.transitions.contains_key(&state) {
53-
self.transitions.insert(state, HashMap::new());
52+
self.transitions.insert(state, BTreeMap::new());
5453
}
5554
self.finals.insert(state);
5655
}
5756
}
5857

59-
impl<S, E> Extend<(S, HashMap<E, HashSet<S>>)> for NFA<S, E>
58+
impl<S, E> NFA<S, E>
59+
where
60+
S: Ord,
61+
E: Ord
62+
{
63+
pub(crate) fn initial(&self) -> &S {
64+
&self.initial
65+
}
66+
67+
pub(crate) fn get(&self, state: &S) -> Option<&BTreeMap<E, BTreeSet<S>>> {
68+
self.transitions.get(state)
69+
}
70+
71+
pub(crate) fn is_final(&self, state: &S) -> bool {
72+
self.finals.contains(state)
73+
}
74+
}
75+
76+
impl<S, E> Extend<(S, BTreeMap<E, BTreeSet<S>>)> for NFA<S, E>
6077
where
61-
S: Copy + Eq + Hash,
62-
E: Copy + Eq + Hash
78+
S: Copy + Ord,
79+
E: Copy + Ord
6380
{
64-
fn extend<T: IntoIterator<Item = (S, HashMap<E, HashSet<S>>)>>(&mut self, iter: T) {
81+
fn extend<T: IntoIterator<Item = (S, BTreeMap<E, BTreeSet<S>>)>>(&mut self, iter: T) {
6582
for (start, transitions) in iter.into_iter() {
6683
for (event, ends) in transitions.into_iter() {
6784
for end in ends.into_iter() {
@@ -72,7 +89,7 @@ where
7289
}
7390
}
7491

75-
type ENFA<S, E> = NFA<S, Option<E>>;
92+
pub(crate) type ENFA<S, E> = NFA<S, Option<E>>;
7693

7794
impl ENFA<u128, char> {
7895
fn _from(re: RE, ids: &mut IDGenerator) -> Self {

src/util.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ impl IDGenerator {
1818
macro_rules! map {
1919
($($x:expr => $y:expr),*) => {{
2020
#[allow(unused_mut)]
21-
let mut temp_hash_map = std::collections::HashMap::new();
21+
let mut temp_map = std::collections::BTreeMap::new();
2222
$(
23-
temp_hash_map.insert($x, $y);
23+
temp_map.insert($x, $y);
2424
)*
25-
temp_hash_map
25+
temp_map
2626
}}
2727
}
2828

2929
#[macro_export]
3030
macro_rules! set {
3131
($($x:expr),*) => {{
3232
#[allow(unused_mut)]
33-
let mut temp_hash_set = std::collections::HashSet::new();
33+
let mut temp_set = std::collections::BTreeSet::new();
3434
$(
35-
temp_hash_set.insert($x);
35+
temp_set.insert($x);
3636
)*
37-
temp_hash_set
37+
temp_set
3838
}}
3939
}
4040

0 commit comments

Comments
 (0)