Skip to content

Commit 637add2

Browse files
committed
Encapsulate DFA construction kludge.
Today I learned how to make associated functions in Rust! This makes a lot of other code much more readable.
1 parent f262762 commit 637add2

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

src/lib.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ struct DFAState {
1818
state_id: StateID
1919
}
2020

21+
22+
impl DFAState {
23+
/// Encapsulate the kluge necessary to set up the DFA correctly for Syncode's use case.
24+
fn new(
25+
regex: &str
26+
) -> DFAState {
27+
let dfa = dense::DFA::new(regex).unwrap();
28+
// We always want the DFA to match starting from the beginning of the string.
29+
let config = start::Config::new().anchored(Anchored::Yes);
30+
let state_id = dfa.start_state(&config).unwrap();
31+
DFAState{dfa: dfa.into(), state_id}
32+
}
33+
}
34+
35+
2136
/// Compute whether the string could match a sequence of terminals starting at a certain state in the first DFA.
2237
///
2338
/// Given a DFA D(Q, Σ, δ, q0, F ), a string w ∈ Σ∗, a DFA state q ∈ Q and any sequence of terminals Λ = {τf +1, τf +2 . . . τf +d}, dmatch(w, q, Λ) = true, if either of the following conditions hold:
@@ -61,14 +76,13 @@ fn dmatch(string: &str, starting_state: &DFAState, sequence_of_terminals: Vec<&s
6176
continue
6277
}
6378
// Compile the dfa for the next terminal.
64-
let new_dfa = dense::Builder::new()
65-
.configure(dense::DFA::config().start_kind(dfa::StartKind::Anchored))
66-
.build(&sequence_of_terminals[0]).unwrap();
67-
let new_starting_state = new_dfa.start_state(&start::Config::new().anchored(Anchored::Yes)).unwrap();
79+
let new_dfa = DFAState::new(&sequence_of_terminals[0]);
6880
// Call recursively.
69-
return dmatch(&string[i..],
70-
&DFAState{dfa: new_dfa.into(), state_id: new_starting_state},
71-
sequence_of_terminals[1..].to_vec());
81+
return dmatch(
82+
&string[i..],
83+
&new_dfa,
84+
sequence_of_terminals[1..].to_vec(),
85+
);
7286

7387
}
7488

@@ -148,21 +162,15 @@ mod tests {
148162
#[test]
149163
fn test_dmatch_case1() {
150164
let candidate_string = "abba";
151-
let dfa = dense::DFA::new(r"[ab]*cd").unwrap();
152-
let config = start::Config::new().anchored(Anchored::Yes);
153-
let state_id = dfa.start_state(&config).unwrap();
154-
let starting_state = DFAState{dfa: dfa.into(), state_id};
165+
let starting_state = DFAState::new(r"[ab]*cd");
155166
let accept_sequence: Vec<&str> = Vec::new();
156167
assert!(dmatch(candidate_string, &starting_state, accept_sequence));
157168
}
158169

159170
#[test]
160171
fn test_dmatch_case2() {
161172
let candidate_string = "abbacdd";
162-
let dfa = dense::DFA::new(r"[ab]*").unwrap();
163-
let config = start::Config::new().anchored(Anchored::Yes);
164-
let state_id = dfa.start_state(&config).unwrap();
165-
let starting_state = DFAState{dfa: dfa.into(), state_id};
173+
let starting_state = DFAState::new(r"[ab]*");
166174
let accept_sequence: Vec<&str> = Vec::new();
167175
assert!(dmatch(candidate_string, &starting_state, accept_sequence));
168176
}
@@ -171,10 +179,7 @@ mod tests {
171179
fn test_dmatch_case3() {
172180
// Illustrative example from page 12 of the paper.
173181
let candidate_string = "is_prime():";
174-
let dfa = dense::DFA::new(r"[[a-z][A-Z]_]*").unwrap();
175-
let config = start::Config::new().anchored(Anchored::Yes);
176-
let state_id = dfa.start_state(&config).unwrap();
177-
let starting_state = DFAState{dfa: dfa.into(), state_id};
182+
let starting_state = DFAState::new(r"[a-zA-Z_]*");
178183
let accept_sequence = [r"\(", r"\)"].to_vec();
179184
assert!(dmatch(candidate_string, &starting_state, accept_sequence));
180185
}

0 commit comments

Comments
 (0)