diff --git a/regex/matching.go b/regex/matching.go index 23f8317..760f7c1 100644 --- a/regex/matching.go +++ b/regex/matching.go @@ -277,6 +277,7 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in //startIdx := offset //endIdx := offset currentStates := make([]nfaState, 0) + nextStates := make([]nfaState, 0) // tempStates := make([]*nfaState, 0) // Used to store states that should be used in next loop iteration i := offset // Index in string //startingFrom := i // Store starting index @@ -311,103 +312,106 @@ func findAllSubmatchHelper(start *nfaState, str []rune, offset int, numGroups in var foundMatch bool var isEmptyAndNoAssertion bool // Main loop - for len(currentStates) > 0 { - currentState, _ := pop(¤tStates) - idx := currentState.threadSP - foundMatch = false - isEmptyAndNoAssertion = false - - if currentState.threadGroups == nil { - currentState.threadGroups = newMatch(numGroups + 1) - currentState.threadGroups[0].StartIdx = idx - } - - if currentState.groupBegin { - currentState.threadGroups[currentState.groupNum].StartIdx = idx - } + for idx := i; idx <= len(str); idx++ { + for currentStateIdx := 0; currentStateIdx < len(currentStates); currentStateIdx++ { + currentState := currentStates[currentStateIdx] + foundMatch = false + isEmptyAndNoAssertion = false + + if currentState.threadGroups == nil { + currentState.threadGroups = newMatch(numGroups + 1) + currentState.threadGroups[0].StartIdx = idx + } - if currentState.groupEnd { - currentState.threadGroups[currentState.groupNum].EndIdx = idx - } + if currentState.groupBegin { + currentState.threadGroups[currentState.groupNum].StartIdx = idx + } - // if currentState.isKleene { - // // Append the next-state (after the kleene), then append the kleene state - // allMatches := make([]*nfaState, 0) - // for _, v := range currentState.transitions { - // allMatches = append(allMatches, v...) - // } - // slices.Reverse(allMatches) - // for _, m := range allMatches { - // m.threadGroups = currentState.threadGroups - // m.threadSP = idx - // } - // currentStates = append(currentStates, allMatches...) - // - // // kleeneState := currentState.kleeneState - // // kleeneState.threadGroups = currentState.threadGroups - // // kleeneState.threadSP = currentState.threadSP - // // currentStates = append(currentStates, kleeneState) - // continue - // } - - // Alternation - enqueue left then right state, and continue - if currentState.isAlternation { - rightState := currentState.rightState - copyThread(rightState, currentState) - currentStates = append(currentStates, *currentState.rightState) - leftState := currentState.leftState - copyThread(leftState, currentState) - currentStates = append(currentStates, *currentState.leftState) - continue - } + if currentState.groupEnd { + currentState.threadGroups[currentState.groupNum].EndIdx = idx + } - // Empty state - enqueue next state, do _not_ increment the SP - if currentState.isEmpty && currentState.assert == noneAssert { - isEmptyAndNoAssertion = true - } + // if currentState.isKleene { + // // Append the next-state (after the kleene), then append the kleene state + // allMatches := make([]*nfaState, 0) + // for _, v := range currentState.transitions { + // allMatches = append(allMatches, v...) + // } + // slices.Reverse(allMatches) + // for _, m := range allMatches { + // m.threadGroups = currentState.threadGroups + // m.threadSP = idx + // } + // currentStates = append(currentStates, allMatches...) + // + // // kleeneState := currentState.kleeneState + // // kleeneState.threadGroups = currentState.threadGroups + // // kleeneState.threadSP = currentState.threadSP + // // currentStates = append(currentStates, kleeneState) + // continue + // } + + // Alternation - enqueue left then right state, and continue + if currentState.isAlternation { + leftState := currentState.leftState + copyThread(leftState, currentState) + currentStates = append(currentStates, *currentState.leftState) + rightState := currentState.rightState + copyThread(rightState, currentState) + currentStates = append(currentStates, *currentState.rightState) + continue + } - if currentState.contentContains(str, idx) { - foundMatch = true - } + // Empty state - enqueue next state, do _not_ increment the SP + if currentState.isEmpty && currentState.assert == noneAssert { + isEmptyAndNoAssertion = true + } - if isEmptyAndNoAssertion || foundMatch { - allMatches := make([]nfaState, 0) - for _, v := range currentState.transitions { - dereferenced := funcMap(v, func(s *nfaState) nfaState { - return *s - }) - allMatches = append(allMatches, dereferenced...) + if currentState.contentContains(str, idx) { + foundMatch = true } - slices.Reverse(allMatches) - for i := range allMatches { - copyThread(&allMatches[i], currentState) - if foundMatch && currentState.assert == noneAssert { - allMatches[i].threadSP += 1 + + if isEmptyAndNoAssertion || foundMatch { + allMatches := make([]nfaState, 0) + for _, v := range currentState.transitions { + dereferenced := funcMap(v, func(s *nfaState) nfaState { + return *s + }) + allMatches = append(allMatches, dereferenced...) } + slices.Reverse(allMatches) + for i := range allMatches { + copyThread(&allMatches[i], currentState) + if foundMatch && currentState.assert == noneAssert { + allMatches[i].threadSP += 1 + } + } + nextStates = append(nextStates, allMatches...) } - currentStates = append(currentStates, allMatches...) - } - if currentState.isLast { // Last state reached - if foundMatch { - if currentState.assert != noneAssert { + if currentState.isLast { // Last state reached + if foundMatch { + if currentState.assert != noneAssert { + currentState.threadGroups[0].EndIdx = idx + } else { + currentState.threadGroups[0].EndIdx = idx + 1 + } + if idx == currentState.threadGroups[0].StartIdx { + idx += 1 + } + return true, currentState.threadGroups, idx + } else if currentState.isEmpty && currentState.assert == noneAssert { currentState.threadGroups[0].EndIdx = idx - } else { - currentState.threadGroups[0].EndIdx = idx + 1 + if idx == currentState.threadGroups[0].StartIdx { + idx++ + } + return true, currentState.threadGroups, idx } - if idx == currentState.threadGroups[0].StartIdx { - idx += 1 - } - return true, currentState.threadGroups, idx - } else if currentState.isEmpty && currentState.assert == noneAssert { - currentState.threadGroups[0].EndIdx = idx - if idx == currentState.threadGroups[0].StartIdx { - idx++ - } - return true, currentState.threadGroups, idx - } + } } + copy(currentStates, nextStates) + nextStates = nil } return false, []Group{}, i + 1 // zeroStates := make([]*nfaState, 0)