More progress on backreference implementation

implementBackreferences
Aadhavan Srinivasan 4 weeks ago
parent 8327450dd2
commit f466d4a8d5

@ -228,45 +228,25 @@ func (re Reg) FindAllStringSubmatch(str string) [][]string {
return rtv 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 {
func addStateToList(str []rune, idx int, list []nfaState, state nfaState, threadGroups []Group, visited []nfaState, preferLongest bool) ([]nfaState, int) {
if stateExists(list, state) || stateExists(visited, state) { if stateExists(list, state) || stateExists(visited, state) {
return list, idx return list
} }
visited = append(visited, state) 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 { if state.isKleene || state.isQuestion {
copyThread(state.splitState, state) 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) copyThread(state.next, state)
list, newIdx = addStateToList(str, newIdx, list, *state.next, threadGroups, visited, preferLongest) list = addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest)
return list, newIdx return list
} }
if state.isAlternation { if state.isAlternation {
copyThread(state.next, state) 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) copyThread(state.splitState, state)
list, newIdx = addStateToList(str, newIdx, list, *state.splitState, threadGroups, visited, preferLongest) list = addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest)
return list, newIdx return list
} }
state.threadGroups = append([]Group{}, threadGroups...) state.threadGroups = append([]Group{}, threadGroups...)
if state.assert != noneAssert { if state.assert != noneAssert {
@ -285,7 +265,7 @@ func addStateToList(str []rune, idx int, list []nfaState, state nfaState, thread
copyThread(state.next, state) copyThread(state.next, state)
return addStateToList(str, idx, list, *state.next, state.threadGroups, visited, preferLongest) 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 = newMatch(numGroups + 1)
start.threadGroups[0].StartIdx = i 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 var match Match = nil
for idx := i; idx <= len(str); idx++ { for idx := i; idx <= len(str); idx++ {
if len(currentStates) == 0 { if len(currentStates) == 0 {
@ -335,14 +315,26 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in
if !preferLongest { if !preferLongest {
break 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) { if currentState.contentContains(str, idx, preferLongest) {
var newIdx int nextStates = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil, preferLongest)
nextStates, newIdx = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil, preferLongest) }
idx = newIdx - 1 } 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...) currentStates = append([]nfaState{}, nextStates...)
nextStates = nil nextStates = nil
} }

Loading…
Cancel
Save