Fixed bug with lookaheads: f(?=f) would not match anything in 'ffa', because of the 'a' at the end of the string. Fixed by checking if there are other last states when an assertion fails, rather than immediately aborting

master
Aadhavan Srinivasan 4 weeks ago
parent fe1136c54c
commit 0de3a94ce3

@ -173,6 +173,8 @@ func findAllMatchesHelper(start *State, str []rune, offset int) (bool, MatchInde
// Take any transitions corresponding to current character // Take any transitions corresponding to current character
numStatesMatched := 0 // The number of states which had at least 1 match for this round 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 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 { for _, state := range currentStates {
matches, numMatches := state.matchesFor(str, i) matches, numMatches := state.matchesFor(str, i)
if numMatches > 0 { if numMatches > 0 {
@ -184,16 +186,30 @@ func findAllMatchesHelper(start *State, str []rune, offset int) (bool, MatchInde
assertionFailed = true assertionFailed = true
} }
if state.isLast { if state.isLast {
endIdx = i lastStateInList = true
tempIndices, _ = unique_append(tempIndices, MatchIndex{startIdx, endIdx})
} }
} }
if assertionFailed && numStatesMatched == 0 { // Nothing has matched and an assertion has failed - abort
if i == startingFrom { if assertionFailed && numStatesMatched == 0 { // Nothing has matched and an assertion has failed
i++ // 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 // Check if we can find a zero-length match
if foundPath == false { if foundPath == false {
if zeroMatchPossible(str, i, currentStates...) { 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, // Only add the match if the start index is in bounds. If the state has an assertion,
// make sure the assertion checks out. // make sure the assertion checks out.
if state.isLast && startIdx < len(str) { 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 endIdx = i
tempIndices, _ = unique_append(tempIndices, MatchIndex{startIdx, endIdx}) tempIndices, _ = unique_append(tempIndices, MatchIndex{startIdx, endIdx})
} }

Loading…
Cancel
Save