ref: ec5f2d23637dadf6d2893bf6f2f829b070ec3b34
parent: 167228d8551ba8b4dc282489258ad2e50363a56f
author: Ori Bernstein <[email protected]>
date: Mon May 23 17:09:46 EDT 2016
Add suball functionality. Search, but with substitution.
--- a/lib/regex/interp.myr
+++ b/lib/regex/interp.myr
@@ -7,6 +7,8 @@
const search : (re : regex#, str : byte[:] -> std.option(byte[:][:]))
const sub : (re : regex#, str : byte[:], subst : byte[:][:] -> std.option(byte[:]))
const sbsub : (sb : std.strbuf#, re : regex#, str : byte[:], subst : byte[:][:] -> bool)
+ const suball : (re : regex#, str : byte[:], subst : byte[:][:] -> byte[:])
+ const sbsuball : (sb : std.strbuf#, re : regex#, str : byte[:], subst : byte[:][:] -> void)
const matchfree : (pat : byte[:][:] -> void)
;;
@@ -69,24 +71,59 @@
if thr == Zthr
m = false
else
- m = dosubst(sb, re, thr, subst)
+ m = dosubst(sb, re, thr, str, subst)
;;
cleanup(re)
-> m
}
-const dosubst = {sb, re, thr, subst
+const suball = {re, str, subst
+ var sb
+
+ sb = std.mksb()
+ sbsuball(sb, re, str, subst)
+ -> std.sbfin(sb)
+}
+
+const sbsuball = {sb, re, str, subst
+ var thr, len, s, i
+
+ /* we always have m[0] as the full match */
+ if re.nmatch != subst.len + 1
+ -> void
+ ;;
+
+ i = 0
+ while i < str.len
+ re.str = str[i:]
+ re.strp = 0
+ thr = run(re, false)
+ if thr == Zthr
+ std.sbputb(sb, str[i])
+ i++
+ else
+ len = thr.mend[0]
+ s = str[i:len + i]
+ dosubst(sb, re, thr, s, subst)
+ i += len
+ ;;
+ cleanup(re)
+ ;;
+}
+
+
+const dosubst = {sb, re, thr, str, subst
var off
off = 0
for var i = 1; i < re.nmatch; i++
if thr.mstart[i] != -1 && thr.mend[i] != -1
- std.sbputs(sb, re.str[off:thr.mstart[i]])
+ std.sbputs(sb, str[off:thr.mstart[i]])
std.sbputs(sb, subst[i - 1])
off = thr.mend[i]
;;
;;
- std.sbputs(sb, re.str[off:])
+ std.sbputs(sb, str[off:])
thrfree(re, thr)
-> true
}
--- a/lib/regex/test/subst.myr
+++ b/lib/regex/test/subst.myr
@@ -49,4 +49,10 @@
"abc123foobar", \
["XYZ", "ABC"][:], \
`std.None)
+
+ /* suball */
+ testsuball("([a-z]*)_", \
+ "a_1bb_2ccccccc_12d", \
+ ["---"][:], \
+ `std.Some "---_1---_2---_12d")
}
--- a/lib/regex/test/testmatch.myr
+++ b/lib/regex/test/testmatch.myr
@@ -8,6 +8,12 @@
expected : std.option(byte[:][:]) \
-> void)
+ const testsearch : ( \
+ pat : byte[:], \
+ text : byte[:], \
+ expected : std.option(byte[:][:]) \
+ -> void)
+
const testsub : ( \
pat : byte[:], \
text : byte[:], \
@@ -15,10 +21,11 @@
expected : std.option(byte[:]) \
-> void)
- const testsearch : ( \
+ const testsuball : ( \
pat : byte[:], \
text : byte[:], \
- expected : std.option(byte[:][:]) \
+ sub : byte[:][:], \
+ expected : std.option(byte[:]) \
-> void)
const dbgmatch : ( \
@@ -37,18 +44,27 @@
}
const testsub = {pat, text, sub, expected
- subst(regex.compile(pat), pat, text, sub, expected)
+ subst(regex.compile(pat), pat, text, sub, expected, false)
}
+const testsuball = {pat, text, sub, expected
+ subst(regex.compile(pat), pat, text, sub, expected, true)
+}
+
const dbgmatch = {pat, text, expected
run(regex.dbgcompile(pat, true), pat, text, expected, false)
}
-const subst = {regex, pat, text, sub, expected
- var re
+const subst = {regex, pat, text, sub, expected, all
+ var re, r
re = std.try(regex)
- match regex.sub(re, text, sub)
+ if all
+ r = `std.Some regex.suball(re, text, sub)
+ else
+ r = regex.sub(re, text, sub)
+ ;;
+ match r
| `std.Some res:
std.put("res: {}\n", res)
match expected