Skip to content

Commit 7cbaecf

Browse files
committed
Added combinators for Thompson NFAs
1 parent a1a8ae1 commit 7cbaecf

File tree

3 files changed

+124
-23
lines changed

3 files changed

+124
-23
lines changed

src/nfa.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/regex.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{collections::BTreeSet, ops::Range};
22

3-
use crate::nfa::ThompsonNFA;
3+
use crate::nfa::NFA;
44

55
#[derive(Clone, PartialEq, Eq)]
66
struct Alphabet {
@@ -23,7 +23,7 @@ struct Regex {
2323
ast: Ast,
2424
}
2525

26-
fn thompsons_construction(regex: Regex) -> ThompsonNFA {
26+
fn thompsons_construction(regex: Regex) -> NFA {
2727
match regex.ast {
2828
Ast::Empty => todo!(),
2929
Ast::Literal(_) => todo!(),

src/thompson.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2+
struct State(usize);
3+
4+
impl State {
5+
fn shifted(&self, amount: usize) -> Self {
6+
State(self.0 + amount)
7+
}
8+
}
9+
10+
enum Transitions {
11+
None,
12+
OneCharacter(char, State),
13+
OneEpsilon(State),
14+
TwoEpsilon(State, State),
15+
}
16+
17+
impl Transitions {
18+
fn shifted(&self, amount: usize) -> Self {
19+
match self {
20+
Transitions::None => Transitions::None,
21+
Transitions::OneCharacter(c, s) => Transitions::OneCharacter(*c, s.shifted(amount)),
22+
Transitions::OneEpsilon(s) => Transitions::OneEpsilon(s.shifted(amount)),
23+
Transitions::TwoEpsilon(s, t) => {
24+
Transitions::TwoEpsilon(s.shifted(amount), t.shifted(amount))
25+
}
26+
}
27+
}
28+
}
29+
30+
pub struct NFA {
31+
transitions: Vec<Transitions>,
32+
initial_state: State,
33+
accepting_state: State,
34+
}
35+
36+
// fn subset_construction(nfa: &NFA) -> DFA {
37+
// todo!()
38+
// }
39+
40+
impl NFA {
41+
pub fn empty() -> Self {
42+
Self {
43+
initial_state: State(0),
44+
accepting_state: State(1),
45+
transitions: vec![Transitions::OneEpsilon(State(1)), Transitions::None],
46+
}
47+
}
48+
49+
pub fn character(c: char) -> Self {
50+
Self {
51+
initial_state: State(0),
52+
accepting_state: State(1),
53+
transitions: vec![Transitions::OneCharacter(c, State(1)), Transitions::None],
54+
}
55+
}
56+
57+
pub fn concatenation(self, other: Self) -> Self {
58+
let other = other.shifted(self.size() - 1);
59+
Self {
60+
accepting_state: other.accepting_state,
61+
transitions: {
62+
let mut transitions = self.transitions;
63+
transitions.pop();
64+
transitions.extend(other.transitions);
65+
transitions
66+
},
67+
..self
68+
}
69+
}
70+
71+
pub fn union(self, other: Self) -> Self {
72+
let this = self.shifted(1);
73+
let other = other.shifted(this.size() + 1);
74+
75+
Self {
76+
initial_state: State(0),
77+
accepting_state: State(this.size() + other.size() + 1),
78+
transitions: {
79+
let mut transitions = vec![Transitions::TwoEpsilon(
80+
this.initial_state,
81+
other.initial_state,
82+
)];
83+
transitions.extend(this.transitions);
84+
transitions.extend(other.transitions);
85+
transitions.push(Transitions::None);
86+
transitions
87+
},
88+
}
89+
}
90+
91+
pub fn kleene_star(self) -> Self {
92+
let this = self.shifted(1);
93+
let accepting_state = State(this.size() + 1);
94+
Self {
95+
initial_state: State(0),
96+
accepting_state,
97+
transitions: {
98+
let mut transitions =
99+
vec![Transitions::TwoEpsilon(this.initial_state, accepting_state)];
100+
transitions.extend(this.transitions);
101+
transitions.push(Transitions::None);
102+
transitions
103+
},
104+
}
105+
}
106+
107+
fn size(&self) -> usize {
108+
self.transitions.len()
109+
}
110+
111+
fn shifted(self, amount: usize) -> Self {
112+
Self {
113+
initial_state: self.initial_state.shifted(amount),
114+
accepting_state: self.accepting_state.shifted(amount),
115+
transitions: self
116+
.transitions
117+
.into_iter()
118+
.map(|t| t.shifted(amount))
119+
.collect(),
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)