Implement Backreferences #3
@@ -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,13 +315,25 @@ 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
|
||||||
|
Reference in New Issue
Block a user