Skip to content

Commit

Permalink
[WIP] fix #nim-lang/RFCs/issues/84 generic parse
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Jan 17, 2019
1 parent 2039dad commit 26188b4
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions compiler/conv.nim
Original file line number Diff line number Diff line change
@@ -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]

0 comments on commit 26188b4

Please sign in to comment.