The example from here:
const
etc_passwd = """root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
messagebus:x:103:107::/var/run/dbus:/bin/false
"""
proc parsePasswd(content: string): seq[string] =
result = @[]
var idx = 0
while true:
var entry = ""
if scanp(content, idx, +(~{'\L', '\0'} -> entry.add($_)), '\L'):
result.add entry
else:
break
when called with echo parsePasswd(etc_passwd) throws: Error: unhandled exception: index out of bounds [IndexError]
Let's turn this into a intermediate(?) hacktoberfest task.
A few hints:
-d:debugScanpatom is implemented~ (not) operator is implementedatom checks for for EOF and the character check itself so ~(expr) will return true if:expr failsA sketch of a possible solution to get you started:
diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim
index 77763ff43..6d78f6f52 100644
--- a/lib/pure/strscans.nim
+++ b/lib/pure/strscans.nim
@@ -474,15 +474,15 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
template interf(x): untyped = bindSym(x, brForceOpen)
- proc toIfChain(n: seq[StmtTriple]; idx, res: NimNode; start: int): NimNode =
+ proc toIfChain(n: seq[StmtTriple]; input, idx, res: NimNode; start: int): NimNode =
if start >= n.len: return newAssignment(res, newLit true)
var ifs: NimNode = nil
if n[start].cond.kind == nnkEmpty:
- ifs = toIfChain(n, idx, res, start+1)
+ ifs = toIfChain(n, input, idx, res, start+1)
else:
- ifs = newIfStmt((n[start].cond,
+ ifs = newIfStmt((infix(newCall(ident"hasNxt", input, idx), "and", n[start].cond),
newTree(nnkStmtList, n[start].action,
- toIfChain(n, idx, res, start+1))))
+ toIfChain(n, input, idx, res, start+1))))
result = newTree(nnkStmtList, n[start].init, ifs)
proc attach(x, attached: NimNode): NimNode =
@@ -609,7 +609,7 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
for x in it: conds.add atm(x, input, idx, attached)
var res = genSym(nskVar, "res")
result = (newStmtList(newVarStmt(res, newLit false),
- toIfChain(conds, idx, res, 0)), res, newEmptyNode())
+ toIfChain(conds, input, idx, res, 0)), res, newEmptyNode())
else:
error("invalid pattern")
@@ -620,7 +620,7 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
var conds: seq[StmtTriple] = @[]
for it in pattern:
conds.add atm(it, input, idx, nil)
- result.add toIfChain(conds, idx, res, 0)
+ result.add toIfChain(conds, input, idx, res, 0)
result.add res
when defined(debugScanp):
echo repr result
I think this makes it possible to drop the idx < input.len in atom since we now always check that beforehand so please _check_ if that's possible.
Most helpful comment
Let's turn this into a intermediate(?) hacktoberfest task.
A few hints:
-d:debugScanpatomis implemented~(not) operator is implementedatomchecks for for EOF and the character check itself so~(expr)will return true if:exprfailsA sketch of a possible solution to get you started:
I think this makes it possible to drop the
idx < input.leninatomsince we now always check that beforehand so please _check_ if that's possible.