diff --git a/regex/nfa.go b/regex/nfa.go index 908db67..4ff15fe 100644 --- a/regex/nfa.go +++ b/regex/nfa.go @@ -104,6 +104,26 @@ func cloneStateHelper(stateToClone *nfaState, cloneMap map[*nfaState]*nfaState) return clone } +// Reset any thread-related fields of the NFA starting from the given state. +func resetThreads(start *nfaState) { + visitedMap := make(map[*nfaState]bool) // The value type doesn't matter here + resetThreadsHelper(start, visitedMap) +} + +func resetThreadsHelper(state *nfaState, visitedMap map[*nfaState]bool) { + if _, ok := visitedMap[state]; ok { + return + } + // Assuming it hasn't been visited + state.threadGroups = nil + visitedMap[state] = true + for _, v := range state.transitions { + for _, nextState := range v { + resetThreadsHelper(nextState, visitedMap) + } + } +} + // Checks if the given state's assertion is true. Returns true if the given // state doesn't have an assertion. func (s nfaState) checkAssertion(str []rune, idx int) bool { @@ -274,7 +294,7 @@ func concatenate(s1 *nfaState, s2 *nfaState) *nfaState { } for i := range s1.output { for _, c := range s2.content { // Create transitions for every element in s1's content to s2' - s1.output[i].transitions[c], _ = unique_append(s1.output[i].transitions[c], s2) + s1.output[i].transitions[c], _ = uniqueAppend(s1.output[i].transitions[c], s2) } } s1.output = s2.output @@ -294,11 +314,11 @@ func kleene(s1 nfaState) (*nfaState, error) { toReturn.output = append(toReturn.output, toReturn) for i := range s1.output { for _, c := range toReturn.content { - s1.output[i].transitions[c], _ = unique_append(s1.output[i].transitions[c], toReturn) + s1.output[i].transitions[c], _ = uniqueAppend(s1.output[i].transitions[c], toReturn) } } for _, c := range s1.content { - toReturn.transitions[c], _ = unique_append(toReturn.transitions[c], &s1) + toReturn.transitions[c], _ = uniqueAppend(toReturn.transitions[c], &s1) } return toReturn, nil } @@ -314,10 +334,10 @@ func alternate(s1 *nfaState, s2 *nfaState) *nfaState { // This would lead to multiple instances of the same set of match indices, since both // 's1' states would be considered to match. for _, c := range s1.content { - toReturn.transitions[c], _ = unique_append(toReturn.transitions[c], s1) + toReturn.transitions[c], _ = uniqueAppend(toReturn.transitions[c], s1) } for _, c := range s2.content { - toReturn.transitions[c], _ = unique_append(toReturn.transitions[c], s2) + toReturn.transitions[c], _ = uniqueAppend(toReturn.transitions[c], s2) } toReturn.content = newContents(epsilon) toReturn.isEmpty = true