Skip to content

Commit

Permalink
add ambiguity support for multiple accept states matching in more tha…
Browse files Browse the repository at this point in the history
…n one NFA
  • Loading branch information
Louis-He committed Dec 16, 2024
1 parent 1a51237 commit 84e0541
Showing 1 changed file with 58 additions and 4 deletions.
62 changes: 58 additions & 4 deletions src/dfa/dfa.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::nfa::nfa::NFA;
use std::cmp::min;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::hash::Hash;
Expand Down Expand Up @@ -303,11 +304,22 @@ impl DFA {
// Check if this DFA state is an accept state
for (idx, nfa_state) in nfa_states.iter() {
if nfas.get(*idx).unwrap().get_accept() == *nfa_state {
dfa_to_accepted_nfa_state_mapping
.get_mut(dfa_state.0)
.as_mut()
// check if the node is already an accept state
let registered_accept_state = dfa_to_accepted_nfa_state_mapping
.get(dfa_state.0)
.unwrap()
.replace((*idx, nfa_state.clone()));
.clone();
let is_update = registered_accept_state.is_none()
|| registered_accept_state.unwrap().0 > *idx;

if is_update {
dfa_to_accepted_nfa_state_mapping
.get_mut(dfa_state.0)
.as_mut()
.unwrap()
.replace((*idx, nfa_state.clone()));
}

dfa_accept_states.insert(dfa_state.clone());
}
}
Expand Down Expand Up @@ -521,6 +533,28 @@ mod tests {
Ok(nfa)
}

fn create_nfa4() -> Result<NFA> {
// Should only match "aa"
let mut parser = RegexParser::new();
let parsed_ast = parser.parse_into_ast("aa")?;

let mut nfa = NFA::new();
nfa.add_ast_to_nfa(&parsed_ast, NFA::START_STATE, NFA::ACCEPT_STATE)?;

Ok(nfa)
}

fn create_nfa5() -> Result<NFA> {
// Should only match "ab"
let mut parser = RegexParser::new();
let parsed_ast = parser.parse_into_ast("a*")?;

let mut nfa = NFA::new();
nfa.add_ast_to_nfa(&parsed_ast, NFA::START_STATE, NFA::ACCEPT_STATE)?;

Ok(nfa)
}

#[test]
fn test_nfa1_from_nfa_to_dfa() -> Result<()> {
let nfa = create_nfa1()?;
Expand Down Expand Up @@ -643,6 +677,26 @@ mod tests {
Ok(())
}

#[test]
fn test_ambiguity() -> Result<()> {
let nfa4 = create_nfa4()?;
let nfa5 = create_nfa5()?;

let dfa = DFA::from_multiple_nfas(vec![nfa4, nfa5]);

println!("{:?}", dfa);

// Check correctness given some examples
// Should match:
// "a" or "ab"

// assert_eq!(dfa.simulate("a"), (Some(1usize), true));
assert_eq!(dfa.simulate("aa"), (Some(0usize), true));
// assert_eq!(dfa.simulate("aaa"), (Some(1usize), false));

Ok(())
}

#[test]
fn test_esay_from_multi_nfas_to_dfa_single_char_simulation() -> Result<()> {
let nfa1 = create_nfa1()?;
Expand Down

0 comments on commit 84e0541

Please sign in to comment.