diff --git a/compiler/conv.nim b/compiler/conv.nim new file mode 100644 index 0000000000000..65dd8656a70ce --- /dev/null +++ b/compiler/conv.nim @@ -0,0 +1,85 @@ +#[ +unfinished +generic parser +]# + +import parseutils +from strutils import startsWith, continuesWith + +template enforce(a: untyped, msg: untyped) = + # todo: custom catchable exception + doAssert a, $msg + +proc skipWhitespace(src: string, start: var int) = + while start < src.len and src[start] == ' ': # CHECKME for ws + start.inc + +template skipWhitespace2() = + skipWhitespace(src, start) + +template continuesWith2(pattern: string): bool= + src.continuesWith(pattern, start) + + +template continuesWithAndAdvance(pattern: string): bool= + let old = start + skipWhitespace2() + if src.continuesWith(pattern, start): + start.inc pattern.len + true + else: + start = old + false + +proc eat(src: string, start: var int, pattern: string) = + enforce continuesWithAndAdvance(pattern), (src, start, pattern) + +proc parseFrom*[T](dst: var T, src: string, start: var int) = + template process(parseCustom) = + let ret = parseCustom(src, dst, start) + enforce ret > 0, (start, src) + start += ret + + skipWhitespace2() + when T is seq: + parseFrom(dst, src, start) + elif T is int: process(parseInt) + elif T is float: process(parseFloat) + elif T is bool: + if continuesWithAndAdvance("true"): dst = true + elif continuesWithAndAdvance("false"): dst = false + else: + # else: enforce false, ($T, start, src) # nim BUG cgen error + doAssert false, $($T, start) + else: + static: doAssert false, $T + +proc parseFrom*[T](dst: var seq[T], src: string, start: var int) = + eat(src, start, "@[") + while true: + if continuesWithAndAdvance("]"): return + var a: T + parseFrom(a, src, start) + dst.add a + if continuesWithAndAdvance(","): + continue + else: + break + eat(src, start, "]") + +proc parseFrom*[T](dst: var T, src: string) = + var start = 0 + parseFrom(dst, src, start) + enforce start == src.len, (start, src.len) + +proc parse*[T](src: string): T = + parseFrom(result, src) + +when isMainModule: + proc runTest[T](a: T) = + doAssert a == parse[T]($a), $(a, $a, $T) + runTest 123 + runTest 3.14 + runTest @[1,2] + runTest @[@[1,2], @[3], @[]] + runTest @[true, false]