diff --git a/regex/matching.go b/regex/matching.go index 230a658..3dba3f0 100644 --- a/regex/matching.go +++ b/regex/matching.go @@ -228,45 +228,25 @@ func (re Reg) FindAllStringSubmatch(str string) [][]string { return rtv } -// Second parameter is the 'new index' -func addStateToList(str []rune, idx int, list []nfaState, state nfaState, threadGroups []Group, visited []nfaState, preferLongest bool) ([]nfaState, int) { +func addStateToList(str []rune, idx int, list []nfaState, state nfaState, threadGroups []Group, visited []nfaState, preferLongest bool) []nfaState { if stateExists(list, state) || stateExists(visited, state) { - return list, idx + return list } visited = append(visited, state) - if state.isBackreference { - if threadGroups[state.referredGroup].IsValid() { - groupLength := threadGroups[state.referredGroup].EndIdx - threadGroups[state.referredGroup].StartIdx - if state.threadBackref == groupLength { - state.threadBackref = 0 - copyThread(state.next, state) - return addStateToList(str, idx+groupLength, list, *state.next, threadGroups, visited, preferLongest) - } - idxInReferredGroup := threadGroups[state.referredGroup].StartIdx + state.threadBackref - if idxInReferredGroup < len(str) && idx+state.threadBackref < len(str) && str[idxInReferredGroup] == str[idx+state.threadBackref] { - state.threadBackref += 1 - return addStateToList(str, idx, list, state, threadGroups, visited, preferLongest) - } else { - return list, idx - } - } else { - return list, idx - } - } if state.isKleene || state.isQuestion { copyThread(state.splitState, state) - list, newIdx := addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest) + list := addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest) copyThread(state.next, state) - list, newIdx = addStateToList(str, newIdx, list, *state.next, threadGroups, visited, preferLongest) - return list, newIdx + list = addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest) + return list } if state.isAlternation { copyThread(state.next, state) - list, newIdx := addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest) + list := addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest) copyThread(state.splitState, state) - list, newIdx = addStateToList(str, newIdx, list, *state.splitState, threadGroups, visited, preferLongest) - return list, newIdx + list = addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest) + return list } state.threadGroups = append([]Group{}, threadGroups...) if state.assert != noneAssert { @@ -285,7 +265,7 @@ func addStateToList(str []rune, idx int, list []nfaState, state nfaState, thread copyThread(state.next, state) return addStateToList(str, idx, list, *state.next, state.threadGroups, visited, preferLongest) } - return append(list, state), idx + return append(list, state) } @@ -315,7 +295,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, nil, preferLongest) // We can't go forward at the beginning, so I discard the second retval + currentStates = addStateToList(str, i, currentStates, *start, start.threadGroups, nil, preferLongest) var match Match = nil for idx := i; idx <= len(str); idx++ { if len(currentStates) == 0 { @@ -335,13 +315,25 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in if !preferLongest { break } - } else if !currentState.isAlternation && !currentState.isKleene && !currentState.isQuestion && !currentState.groupBegin && !currentState.groupEnd && currentState.assert == noneAssert { // Normal character + } else if !currentState.isAlternation && !currentState.isKleene && !currentState.isQuestion && !currentState.isBackreference && !currentState.groupBegin && !currentState.groupEnd && currentState.assert == noneAssert { // Normal character if currentState.contentContains(str, idx, preferLongest) { - var newIdx int - nextStates, newIdx = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil, preferLongest) - idx = newIdx - 1 + nextStates = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil, preferLongest) + } + } else if currentState.isBackreference { + groupLength := currentState.threadGroups[currentState.referredGroup].EndIdx - currentState.threadGroups[currentState.referredGroup].StartIdx + if currentState.threadBackref == groupLength { + currentState.threadBackref = 0 + copyThread(currentState.next, currentState) + currentStates = addStateToList(str, idx, currentStates, *currentState.next, currentState.threadGroups, nil, preferLongest) + } else { + idxInReferredGroup := currentState.threadGroups[currentState.referredGroup].StartIdx + currentState.threadBackref + if idxInReferredGroup < len(str) && idx < len(str) && str[idxInReferredGroup] == str[idx] { + currentState.threadBackref += 1 + nextStates = append(nextStates, currentState) + } } } + } currentStates = append([]nfaState{}, nextStates...) nextStates = nil