diff --git a/matching.go b/matching.go index c66971e..cc47d50 100644 --- a/matching.go +++ b/matching.go @@ -173,6 +173,8 @@ func findAllMatchesHelper(start *State, str []rune, offset int) (bool, MatchInde // Take any transitions corresponding to current character numStatesMatched := 0 // The number of states which had at least 1 match for this round assertionFailed := false // Whether or not an assertion failed for this round + lastStateInList := false // Whether or not a last state was in our list of states + // lastStateLookaround := false // Whether or not a last state (that is also a lookaround) matched for _, state := range currentStates { matches, numMatches := state.matchesFor(str, i) if numMatches > 0 { @@ -184,16 +186,30 @@ func findAllMatchesHelper(start *State, str []rune, offset int) (bool, MatchInde assertionFailed = true } if state.isLast { - endIdx = i - tempIndices, _ = unique_append(tempIndices, MatchIndex{startIdx, endIdx}) + lastStateInList = true } } - if assertionFailed && numStatesMatched == 0 { // Nothing has matched and an assertion has failed - abort - if i == startingFrom { - i++ + + if assertionFailed && numStatesMatched == 0 { // Nothing has matched and an assertion has failed + // One of the states in our list was a last state. In this case, we + // don't abort upon the failure of an assertion, because we have found + // another path to a final state. + // Even if the last state _was_ an assertion, we can use the previously + // saved indices to find a match. + if lastStateInList { + break + } else { + if i == startingFrom { + i++ + } + return false, MatchIndex{}, i } - return false, MatchIndex{}, i } + if lastStateInList { // A last-state was in the list of states. add the matchIndex to our MatchIndex list + endIdx = i + tempIndices, _ = unique_append(tempIndices, MatchIndex{startIdx, endIdx}) + } + // Check if we can find a zero-length match if foundPath == false { if zeroMatchPossible(str, i, currentStates...) { @@ -250,7 +266,7 @@ func findAllMatchesHelper(start *State, str []rune, offset int) (bool, MatchInde // Only add the match if the start index is in bounds. If the state has an assertion, // make sure the assertion checks out. if state.isLast && startIdx < len(str) { - if state.assert == NONE || state.checkAssertion(str, len(str)) { + if state.assert == NONE || state.checkAssertion(str, i) { endIdx = i tempIndices, _ = unique_append(tempIndices, MatchIndex{startIdx, endIdx}) }