fix bugs in implementation for 'Nfa.getMatchesInRange'
This commit is contained in:
@@ -169,194 +169,43 @@ struct
|
|||||||
end
|
end
|
||||||
|
|
||||||
local
|
local
|
||||||
fun backtrackRange
|
fun loop (pos, buffer, nfa, origNfa, startPos, acc, lastIdx) =
|
||||||
(hd, tl, prevStrings, origNfa, acc, absIdx, startIdx, finishIdx) =
|
if pos = #textLength buffer then
|
||||||
case prevStrings of
|
acc
|
||||||
prevHd :: prevTl =>
|
else if pos > lastIdx then
|
||||||
let
|
|
||||||
val prevIdx = absIdx - String.size prevHd
|
|
||||||
val tl = hd :: tl
|
|
||||||
in
|
|
||||||
if startIdx < prevIdx then
|
|
||||||
(* keep backtracking *)
|
|
||||||
backtrackRange
|
|
||||||
( prevHd
|
|
||||||
, tl
|
|
||||||
, prevTl
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, prevIdx
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val strIdx = startIdx - prevIdx + 1
|
|
||||||
val absIdx = absIdx + strIdx
|
|
||||||
in
|
|
||||||
loop
|
|
||||||
( strIdx
|
|
||||||
, prevHd
|
|
||||||
, tl
|
|
||||||
, prevTl
|
|
||||||
, origNfa
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, absIdx
|
|
||||||
, absIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
| [] => raise Fail "nfa.sml 188: should not backtrack to empty list"
|
|
||||||
|
|
||||||
and loop
|
|
||||||
( strIdx
|
|
||||||
, hd
|
|
||||||
, tl
|
|
||||||
, prevStrings
|
|
||||||
, nfa
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, absIdx
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
) =
|
|
||||||
if strIdx = String.size hd then
|
|
||||||
case tl of
|
|
||||||
newHd :: newTl =>
|
|
||||||
loop
|
|
||||||
( 0
|
|
||||||
, newHd
|
|
||||||
, newTl
|
|
||||||
, hd :: prevStrings
|
|
||||||
, nfa
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, absIdx
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
| [] => acc
|
|
||||||
else if absIdx > finishIdx then
|
|
||||||
acc
|
acc
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val chr = String.sub (hd, strIdx)
|
val chr = LineGap.substring (pos, 1, buffer)
|
||||||
val (nfa, state) = rebuild (nfa, chr, absIdx)
|
val chr = String.sub (chr, 0)
|
||||||
|
val (nfa, state) = rebuild (nfa, chr, pos)
|
||||||
in
|
in
|
||||||
case state of
|
case state of
|
||||||
UNTESTED =>
|
VALID finishIdx =>
|
||||||
loop
|
|
||||||
( strIdx + 1
|
|
||||||
, hd
|
|
||||||
, tl
|
|
||||||
, prevStrings
|
|
||||||
, nfa
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, absIdx + 1
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
| VALID foundIdx =>
|
|
||||||
let
|
let
|
||||||
val acc = PersistentVector.append (startIdx, foundIdx, acc)
|
val acc = PersistentVector.append (startPos, finishIdx, acc)
|
||||||
in
|
in
|
||||||
loop
|
loop
|
||||||
( strIdx + 1
|
( finishIdx + 1
|
||||||
, hd
|
, buffer
|
||||||
, tl
|
|
||||||
, prevStrings
|
|
||||||
, origNfa
|
, origNfa
|
||||||
, origNfa
|
, origNfa
|
||||||
|
, finishIdx + 1
|
||||||
, acc
|
, acc
|
||||||
, foundIdx + 1
|
, lastIdx
|
||||||
, foundIdx + 1
|
|
||||||
, finishIdx
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
| INVALID =>
|
| INVALID =>
|
||||||
let
|
let val pos = startPos + 1
|
||||||
val prevIdx = absIdx - strIdx
|
in loop (pos, buffer, origNfa, origNfa, pos, acc, lastIdx)
|
||||||
in
|
|
||||||
if startIdx < prevIdx then
|
|
||||||
backtrackRange
|
|
||||||
( hd
|
|
||||||
, tl
|
|
||||||
, prevStrings
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, prevIdx
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val strIdx = startIdx - prevIdx + 1
|
|
||||||
val absIdx = prevIdx + strIdx
|
|
||||||
in
|
|
||||||
loop
|
|
||||||
( strIdx
|
|
||||||
, hd
|
|
||||||
, tl
|
|
||||||
, prevStrings
|
|
||||||
, origNfa
|
|
||||||
, origNfa
|
|
||||||
, acc
|
|
||||||
, absIdx
|
|
||||||
, startIdx + 1
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
| UNTESTED =>
|
||||||
|
loop (pos + 1, buffer, nfa, origNfa, startPos, acc, lastIdx)
|
||||||
end
|
end
|
||||||
in
|
in
|
||||||
(* Prerequisite: move buffer to 'start' parameter before calling *)
|
(* Prerequisite: move buffer to 'start' parameter before calling *)
|
||||||
fun getMatchesInRange (startIdx, finishIdx, buffer: LineGap.t, nfa) =
|
fun getMatchesInRange (startIdx, finishIdx, buffer: LineGap.t, nfa) =
|
||||||
let
|
loop (startIdx, buffer, nfa, nfa, 0, PersistentVector.empty, finishIdx)
|
||||||
val {rightStrings, idx = bufferIdx, ...} = buffer
|
|
||||||
val strIdx = startIdx - bufferIdx
|
|
||||||
in
|
|
||||||
case rightStrings of
|
|
||||||
hd :: tl =>
|
|
||||||
if strIdx < String.size hd then
|
|
||||||
(* strIdx is in this string *)
|
|
||||||
loop
|
|
||||||
( strIdx
|
|
||||||
, hd
|
|
||||||
, tl
|
|
||||||
, []
|
|
||||||
, nfa
|
|
||||||
, nfa
|
|
||||||
, PersistentVector.empty
|
|
||||||
, startIdx
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
else
|
|
||||||
(* strIdx is in tl *)
|
|
||||||
(case tl of
|
|
||||||
stlhd :: stltl =>
|
|
||||||
let
|
|
||||||
val strIdx = strIdx - String.size hd
|
|
||||||
in
|
|
||||||
loop
|
|
||||||
( strIdx
|
|
||||||
, stlhd
|
|
||||||
, stltl
|
|
||||||
, []
|
|
||||||
, nfa
|
|
||||||
, nfa
|
|
||||||
, PersistentVector.empty
|
|
||||||
, startIdx
|
|
||||||
, startIdx
|
|
||||||
, finishIdx
|
|
||||||
)
|
|
||||||
end
|
|
||||||
| [] => PersistentVector.empty)
|
|
||||||
| [] => PersistentVector.empty
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Submodule lib/brolib-sml updated: d6e119a161...14bb447289
Reference in New Issue
Block a user