summaryrefslogtreecommitdiff
path: root/lib/regex/interp.myr
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-05-23 14:17:36 -0700
committerOri Bernstein <ori@eigenstate.org>2016-05-23 14:17:36 -0700
commit167228d8551ba8b4dc282489258ad2e50363a56f (patch)
tree27c8d6257bfc63bb9d6523d96ee282309259deba /lib/regex/interp.myr
parent31247e29fb596b44fdd5c18140bc945b6a4b71ce (diff)
downloadmc-167228d8551ba8b4dc282489258ad2e50363a56f.tar.gz
add substitution for full matches.
Diffstat (limited to 'lib/regex/interp.myr')
-rw-r--r--lib/regex/interp.myr49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/regex/interp.myr b/lib/regex/interp.myr
index c52ed25..fbc685e 100644
--- a/lib/regex/interp.myr
+++ b/lib/regex/interp.myr
@@ -5,6 +5,8 @@ use "types"
pkg regex =
const exec : (re : regex#, str : byte[:] -> std.option(byte[:][:]))
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 matchfree : (pat : byte[:][:] -> void)
;;
@@ -42,6 +44,53 @@ const search = {re, str
-> m
}
+const sub = {re, str, subst
+ var sb
+
+ sb = std.mksb()
+ if !sbsub(sb, re, str, subst)
+ -> `std.None
+ else
+ -> `std.Some std.sbfin(sb)
+ ;;
+}
+
+const sbsub = {sb, re, str, subst
+ var thr, m
+
+ /* we always have m[0] as the full match */
+ if re.nmatch != subst.len + 1
+ -> false
+ ;;
+
+ re.str = str
+ re.strp = 0
+ thr = run(re, true)
+ if thr == Zthr
+ m = false
+ else
+ m = dosubst(sb, re, thr, subst)
+ ;;
+ cleanup(re)
+ -> m
+}
+
+const dosubst = {sb, re, thr, 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, subst[i - 1])
+ off = thr.mend[i]
+ ;;
+ ;;
+ std.sbputs(sb, re.str[off:])
+ thrfree(re, thr)
+ -> true
+}
+
const cleanup = {re
var thr, next