summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-05-11 23:31:22 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-05-11 23:31:22 +0200
commit34110fc118a063822c74b9615ff30a2e366aa8d4 (patch)
tree489bc02ea2fd0b47a1f864ed2b00029f0358274b
parent4f9083268f2f977c72027d4f63c0186cd703b15a (diff)
parentfcfe27a1f847cf8cff1b821d82c828841960f121 (diff)
downloadNim-34110fc118a063822c74b9615ff30a2e366aa8d4.tar.gz
Merge pull request #4136 from oderwat/HARA-peg-replace-cb
Added a replace() with callback to pegs.
-rw-r--r--lib/pure/pegs.nim59
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index fead66de2..b5e69595b 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -962,6 +962,50 @@ proc parallelReplace*(s: string, subs: varargs[
   # copy the rest:
   add(result, substr(s, i))
 
+proc replace*(s: string, sub: Peg, cb: proc(
+              match: int, cnt: int, caps: openArray[string]): string): string {.
+              rtl, extern: "npegs$1cb".}=
+  ## Replaces `sub` in `s` by the resulting strings from the callback.
+  ## The callback proc receives the index of the current match (starting with 0),
+  ## the count of captures and an open array with the captures of each match. Examples:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##   proc handleMatches*(m: int, n: int, c: openArray[string]): string =
+  ##     result = ""
+  ##     if m > 0:
+  ##       result.add ", "
+  ##     result.add case n:
+  ##       of 2: c[0].toLower & ": '" & c[1] & "'"
+  ##       of 1: c[0].toLower & ": ''"
+  ##       else: ""
+  ##
+  ##   let s = "Var1=key1;var2=Key2;   VAR3"
+  ##   echo s.replace(peg"{\ident}('='{\ident})* ';'* \s*", handleMatches)
+  ##
+  ## Results in:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##   "var1: 'key1', var2: 'Key2', var3: ''"
+  result = ""
+  var i = 0
+  var caps: array[0..MaxSubpatterns-1, string]
+  var c: Captures
+  var m = 0
+  while i < s.len:
+    c.ml = 0
+    var x = rawMatch(s, sub, i, c)
+    if x <= 0:
+      add(result, s[i])
+      inc(i)
+    else:
+      fillMatches(s, caps, c)
+      add(result, cb(m, c.ml, caps))
+      inc(i, x)
+      inc(m)
+  add(result, substr(s, i))
+
 proc transformFile*(infile, outfile: string,
                     subs: varargs[tuple[pattern: Peg, repl: string]]) {.
                     rtl, extern: "npegs$1".} =
@@ -1789,3 +1833,18 @@ when isMainModule:
 
   assert(str.find(empty_test) == 0)
   assert(str.match(empty_test))
+
+  proc handleMatches*(m: int, n: int, c: openArray[string]): string =
+    result = ""
+
+    if m > 0:
+      result.add ", "
+
+    result.add case n:
+      of 2: c[0].toLower & ": '" & c[1] & "'"
+      of 1: c[0].toLower & ": ''"
+      else: ""
+
+  assert("Var1=key1;var2=Key2;   VAR3".
+         replace(peg"{\ident}('='{\ident})* ';'* \s*",
+         handleMatches)=="var1: 'key1', var2: 'Key2', var3: ''")