Throw an exception when replacing with a nil value

This commit is contained in:
Flaviu Tamas
2015-04-10 13:54:24 -04:00
parent e6d662e6b9
commit 62a8ab9006
3 changed files with 45 additions and 32 deletions

View File

@@ -95,6 +95,8 @@ If `sub` is a string, the syntax is as follows:
- `$#` - first capture
- `$0` - full match
If a given capture is missing, a `ValueError` exception is thrown.
[[proc-escapere]]
==== escapeRe(string): string

View File

@@ -9,6 +9,12 @@ proc fget*[K, V](self: Table[K, V], key: K): V =
const Ident = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
const StartIdent = Ident - {'0'..'9'}
proc checkNil(arg: string): string =
if arg == nil:
raise newException(ValueError, "Cannot use nil capture")
else:
return arg
template formatStr*(howExpr, namegetter, idgetter: expr): expr =
let how = howExpr
var val = newStringOfCap(how.len)
@@ -19,37 +25,38 @@ template formatStr*(howExpr, namegetter, idgetter: expr): expr =
if how[i] != '$':
val.add(how[i])
i += 1
elif how[i + 1] == '$':
val.add('$')
i += 2
elif how[i + 1] == '#':
var id {.inject.} = lastNum
val.add(idgetter)
lastNum += 1
i += 2
elif how[i + 1] in {'0'..'9'}:
i += 1
var id {.inject.} = 0
while i < how.len and how[i] in {'0'..'9'}:
id += (id * 10) + (ord(how[i]) - ord('0'))
i += 1
val.add(idgetter)
lastNum = id + 1
elif how[i + 1] in StartIdent:
i += 1
var name {.inject.} = ""
while i < how.len and how[i] in Ident:
name.add(how[i])
i += 1
val.add(namegetter)
elif how[i + 1] == '{':
i += 2
var name {.inject.} = ""
while i < how.len and how[i] != '}':
name.add(how[i])
i += 1
i += 1
val.add(namegetter)
else:
raise newException(Exception, "Syntax error in format string at " & $i)
if how[i + 1] == '$':
val.add('$')
i += 2
elif how[i + 1] == '#':
var id {.inject.} = lastNum
val.add(checkNil(idgetter))
lastNum += 1
i += 2
elif how[i + 1] in {'0'..'9'}:
i += 1
var id {.inject.} = 0
while i < how.len and how[i] in {'0'..'9'}:
id += (id * 10) + (ord(how[i]) - ord('0'))
i += 1
val.add(checkNil(idgetter))
lastNum = id + 1
elif how[i + 1] in StartIdent:
i += 1
var name {.inject.} = ""
while i < how.len and how[i] in Ident:
name.add(how[i])
i += 1
val.add(checkNil(namegetter))
elif how[i + 1] == '{':
i += 2
var name {.inject.} = ""
while i < how.len and how[i] != '}':
name.add(how[i])
i += 1
i += 1
val.add(checkNil(namegetter))
else:
raise newException(Exception, "Syntax error in format string at " & $i)
val

View File

@@ -14,3 +14,7 @@ suite "replace":
check("123".replace(re"(\d)(\d)", "$#$#") == "123")
check("123".replace(re"(?<foo>\d)(\d)", "$foo$#$#") == "1123")
check("123".replace(re"(?<foo>\d)(\d)", "${foo}$#$#") == "1123")
test "replacing missing captures should throw instead of segfaulting":
expect ValueError: discard "ab".replace(re"(a)|(b)", "$1$2")
expect ValueError: discard "b".replace(re"(a)?(b)", "$1$2")