bugfix: $ escaping in interpolatedFragments

This commit is contained in:
Araq 2011-09-26 07:45:33 +02:00
commit 7c34357856
2 changed files with 22 additions and 12 deletions

View file

@ -269,8 +269,9 @@ proc parseFloat*(s: string, number: var float, start = 0): int {.
type type
TInterpolatedKind* = enum ## describes for `interpolatedFragments` TInterpolatedKind* = enum ## describes for `interpolatedFragments`
## which part of the interpolated string is ## which part of the interpolated string is
## yielded; for example in "str$var${expr}" ## yielded; for example in "str$$$var${expr}"
ikStr, ## ``str`` part of the interpolated string ikStr, ## ``str`` part of the interpolated string
ikDollar, ## escaped ``$`` part of the interpolated string
ikVar, ## ``var`` part of the interpolated string ikVar, ## ``var`` part of the interpolated string
ikExpr ## ``expr`` part of the interpolated string ikExpr ## ``expr`` part of the interpolated string
@ -281,7 +282,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind,
## Example: ## Example:
## ##
## .. code-block:: nimrod ## .. code-block:: nimrod
## for k, v in interpolatedFragments(" $this is ${an example} "): ## for k, v in interpolatedFragments(" $this is ${an example} $$"):
## echo "(", k, ", \"", v, "\")" ## echo "(", k, ", \"", v, "\")"
## ##
## Results in: ## Results in:
@ -291,12 +292,13 @@ iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind,
## (ikExpr, "this") ## (ikExpr, "this")
## (ikString, " is ") ## (ikString, " is ")
## (ikExpr, "an example") ## (ikExpr, "an example")
## (ikString, " ") ## (ikString, " ")
## (ikDollar, "$")
var i = 0 var i = 0
var kind: TInterpolatedKind var kind: TInterpolatedKind
while true: while true:
var j = i var j = i
if s[j] == '$' and s[j+1] != '$': if s[j] == '$':
if s[j+1] == '{': if s[j+1] == '{':
inc j, 2 inc j, 2
var nesting = 0 var nesting = 0
@ -320,11 +322,15 @@ iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind,
while s[j] in IdentChars: inc(j) while s[j] in IdentChars: inc(j)
inc i # skip $ inc i # skip $
kind = ikVar kind = ikVar
elif s[j+1] == '$':
inc j, 2
inc i # skip $
kind = ikDollar
else: else:
raise newException(EInvalidValue, raise newException(EInvalidValue,
"Unable to parse a varible name at " & s[i..s.len]) "Unable to parse a varible name at " & s[i..s.len])
else: else:
while j < s.len and (s[j] != '$' or s[j+1] == '$'): inc j while j < s.len and s[j] != '$': inc j
kind = ikStr kind = ikStr
if j > i: if j > i:
# do not copy the trailing } for ikExpr: # do not copy the trailing } for ikExpr:

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tstringinterp.nim" file: "tstringinterp.nim"
output: "Hello Alice, 64 | Hello Bob, 10" output: "Hello Alice, 64 | Hello Bob, 10$"
""" """
import macros, parseutils, strutils import macros, parseutils, strutils
@ -12,10 +12,10 @@ proc concat(strings: openarray[string]): string =
template ProcessInterpolations(e: expr) = template ProcessInterpolations(e: expr) =
var s = e[1].strVal var s = e[1].strVal
for f in interpolatedFragments(s): for f in interpolatedFragments(s):
if f.kind == ikStr: case f.kind
addString(f.value) of ikStr: addString(f.value)
else: of ikDollar: addDollar()
addExpr(newCall("$", parseExpr(f.value))) of ikVar, ikExpr: addExpr(newCall("$", parseExpr(f.value)))
macro formatStyleInterpolation(e: expr): expr = macro formatStyleInterpolation(e: expr): expr =
var var
@ -30,6 +30,9 @@ macro formatStyleInterpolation(e: expr): expr =
arrayNode.add(e) arrayNode.add(e)
formatString.add("$" & $(idx)) formatString.add("$" & $(idx))
inc idx inc idx
proc addDollar() =
formatString.add("$$")
ProcessInterpolations(e) ProcessInterpolations(e)
@ -43,6 +46,7 @@ macro concatStyleInterpolation(e: expr): expr =
proc addString(s: string) = args.add(newStrLitNode(s)) proc addString(s: string) = args.add(newStrLitNode(s))
proc addExpr(e: expr) = args.add(e) proc addExpr(e: expr) = args.add(e)
proc addDollar() = args.add(newStrLitNode"$")
ProcessInterpolations(e) ProcessInterpolations(e)
@ -62,7 +66,7 @@ var
var var
s1 = concatStyleInterpolation"Hello ${alice}, ${sum(a, b, c)}" s1 = concatStyleInterpolation"Hello ${alice}, ${sum(a, b, c)}"
s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}" s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}$$"
write(stdout, s1 & " | " & s2) write(stdout, s1 & " | " & s2)