diff --git a/automaton.go b/automaton.go index 4014797..41ac73f 100644 --- a/automaton.go +++ b/automaton.go @@ -87,4 +87,5 @@ var alwaysMatchAutomaton = &AlwaysMatch{} type FuzzyAutomaton interface { Automaton EditDistance(int) uint8 + MatchAndDistance(input string) (bool, uint8) } diff --git a/levenshtein/dfa.go b/levenshtein/dfa.go index 3fc26ed..dc8ed08 100644 --- a/levenshtein/dfa.go +++ b/levenshtein/dfa.go @@ -43,6 +43,24 @@ func (d *DFA) EditDistance(stateId int) uint8 { return d.distances[stateId].distance() } +func (d *DFA) MatchAndDistance(input string) (bool, uint8) { + currentState := d.Start() + index := 0 + // Traverse the DFA while characters can still match + for d.CanMatch(currentState) && index < len(input) { + currentState = d.Accept(currentState, input[index]) + if currentState == int(SinkState) { + break + } + index++ + } + // Ensure we've processed the entire input and check if the current state is a match + if index == len(input) && d.IsMatch(currentState) { + return true, d.EditDistance(currentState) + } + return false, 0 +} + // Returns the number of states in the `DFA`. func (d *DFA) numStates() int { return len(d.transitions) diff --git a/regexp/regexp.go b/regexp/regexp.go index 920ddc3..8d28b23 100644 --- a/regexp/regexp.go +++ b/regexp/regexp.go @@ -117,3 +117,14 @@ func (r *Regexp) Accept(s int, b byte) int { } return 0 } + +func (r *Regexp) MatchesRegex(input string) bool { + currentState := r.Start() + index := 0 + // Traverse the DFA while characters can still match + for r.CanMatch(currentState) && index < len(input) { + currentState = r.Accept(currentState, input[index]) + index++ + } + return index == len(input) && r.IsMatch(currentState) +}