Started implementing backreferences (octal values should now be prefaced with \0)

This commit is contained in:
2025-02-11 16:14:48 -05:00
parent 073f231b89
commit 8327450dd2
5 changed files with 156 additions and 39 deletions

View File

@@ -228,25 +228,45 @@ func (re Reg) FindAllStringSubmatch(str string) [][]string {
return rtv
}
func addStateToList(str []rune, idx int, list []nfaState, state nfaState, threadGroups []Group, visited []nfaState, preferLongest bool) []nfaState {
// Second parameter is the 'new index'
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) {
return list
return list, idx
}
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 = addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest)
list, newIdx := addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest)
copyThread(state.next, state)
list = addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest)
return list
list, newIdx = addStateToList(str, newIdx, list, *state.next, threadGroups, visited, preferLongest)
return list, newIdx
}
if state.isAlternation {
copyThread(state.next, state)
list = addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest)
list, newIdx := addStateToList(str, idx, list, *state.next, threadGroups, visited, preferLongest)
copyThread(state.splitState, state)
list = addStateToList(str, idx, list, *state.splitState, threadGroups, visited, preferLongest)
return list
list, newIdx = addStateToList(str, newIdx, list, *state.splitState, threadGroups, visited, preferLongest)
return list, newIdx
}
state.threadGroups = append([]Group{}, threadGroups...)
if state.assert != noneAssert {
@@ -257,13 +277,15 @@ func addStateToList(str []rune, idx int, list []nfaState, state nfaState, thread
}
if state.groupBegin {
state.threadGroups[state.groupNum].StartIdx = idx
copyThread(state.next, state)
return addStateToList(str, idx, list, *state.next, state.threadGroups, visited, preferLongest)
}
if state.groupEnd {
state.threadGroups[state.groupNum].EndIdx = idx
copyThread(state.next, state)
return addStateToList(str, idx, list, *state.next, state.threadGroups, visited, preferLongest)
}
return append(list, state)
return append(list, state), idx
}
@@ -293,7 +315,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)
currentStates, _ = addStateToList(str, i, currentStates, *start, start.threadGroups, nil, preferLongest) // We can't go forward at the beginning, so I discard the second retval
var match Match = nil
for idx := i; idx <= len(str); idx++ {
if len(currentStates) == 0 {
@@ -315,7 +337,9 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in
}
} else if !currentState.isAlternation && !currentState.isKleene && !currentState.isQuestion && !currentState.groupBegin && !currentState.groupEnd && currentState.assert == noneAssert { // Normal character
if currentState.contentContains(str, idx, preferLongest) {
nextStates = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil, preferLongest)
var newIdx int
nextStates, newIdx = addStateToList(str, idx+1, nextStates, *currentState.next, currentState.threadGroups, nil, preferLongest)
idx = newIdx - 1
}
}
}