From f15a5cae348e19b31f4e50358616629a075d4d79 Mon Sep 17 00:00:00 2001 From: Aadhavan Srinivasan Date: Sat, 8 Feb 2025 16:07:01 -0500 Subject: [PATCH] Store all states visited in a single run of 'addStateToList()' in a slice --- regex/matching.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/regex/matching.go b/regex/matching.go index d2925bd..6a5e0e7 100644 --- a/regex/matching.go +++ b/regex/matching.go @@ -251,38 +251,40 @@ func (regex Reg) FindAllSubmatch(str string) []Match { return indices } -func addStateToList(str []rune, idx int, list []nfaState, state nfaState, threadGroups []Group) []nfaState { - if stateExists(list, state) { +func addStateToList(str []rune, idx int, list []nfaState, state nfaState, threadGroups []Group, visited []nfaState) []nfaState { + if stateExists(list, state) || stateExists(visited, state) { return list } + visited = append(visited, state) + if state.isKleene || state.isQuestion { copyThread(state.splitState, state) - list = addStateToList(str, idx, list, *state.splitState, threadGroups) + list = addStateToList(str, idx, list, *state.splitState, threadGroups, visited) copyThread(state.next, state) - list = addStateToList(str, idx, list, *state.next, threadGroups) + list = addStateToList(str, idx, list, *state.next, threadGroups, visited) return list } if state.isAlternation { copyThread(state.next, state) - list = addStateToList(str, idx, list, *state.next, threadGroups) + list = addStateToList(str, idx, list, *state.next, threadGroups, visited) copyThread(state.splitState, state) - list = addStateToList(str, idx, list, *state.splitState, threadGroups) + list = addStateToList(str, idx, list, *state.splitState, threadGroups, visited) return list } state.threadGroups = append([]Group{}, threadGroups...) if state.assert != noneAssert { if state.checkAssertion(str, idx) { copyThread(state.next, state) - return append(list, addStateToList(str, idx, list, *state.next, state.threadGroups)...) + return addStateToList(str, idx, list, *state.next, state.threadGroups, visited) } } if state.groupBegin { state.threadGroups[state.groupNum].StartIdx = idx - return append(list, addStateToList(str, idx, list, *state.next, state.threadGroups)...) + return addStateToList(str, idx, list, *state.next, state.threadGroups, visited) } if state.groupEnd { state.threadGroups[state.groupNum].EndIdx = idx - return append(list, addStateToList(str, idx, list, *state.next, state.threadGroups)...) + return addStateToList(str, idx, list, *state.next, state.threadGroups, visited) } return append(list, state) @@ -344,7 +346,7 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in start.threadGroups = newMatch(numGroups + 1) start.threadGroups[0].StartIdx = i - currentStates = addStateToList(str, i, currentStates, *start, start.threadGroups) + currentStates = addStateToList(str, i, currentStates, *start, start.threadGroups, nil) var match Match = nil // var isEmptyAndNoAssertion bool // Main loop @@ -366,7 +368,7 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in break } else if !currentState.isAlternation && !currentState.isKleene && !currentState.isQuestion && !currentState.groupBegin && !currentState.groupEnd { // Normal character or assertion if currentState.contentContains(str, idx) { - nextStates = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups) + nextStates = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil) } }