Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Andreas Rumpf 2018-01-07 12:21:47 +01:00
commit e23ea64c41
3 changed files with 57 additions and 8 deletions

View file

@ -87,6 +87,23 @@ proc parseOct*(s: string, number: var int, start = 0): int {.
inc(i) inc(i)
if foundDigit: result = i-start if foundDigit: result = i-start
proc parseBin*(s: string, number: var int, start = 0): int {.
rtl, extern: "npuParseBin", noSideEffect.} =
## parses an binary number and stores its value in ``number``. Returns
## the number of the parsed characters or 0 in case of an error.
var i = start
var foundDigit = false
if s[i] == '0' and (s[i+1] == 'b' or s[i+1] == 'B'): inc(i, 2)
while true:
case s[i]
of '_': discard
of '0'..'1':
number = number shl 1 or (ord(s[i]) - ord('0'))
foundDigit = true
else: break
inc(i)
if foundDigit: result = i-start
proc parseIdent*(s: string, ident: var string, start = 0): int = proc parseIdent*(s: string, ident: var string, start = 0): int =
## parses an identifier and stores it in ``ident``. Returns ## parses an identifier and stores it in ``ident``. Returns
## the number of the parsed characters or 0 in case of an error. ## the number of the parsed characters or 0 in case of an error.

View file

@ -31,7 +31,10 @@ As can be seen from the examples, strings are matched verbatim except for
substrings starting with ``$``. These constructions are available: substrings starting with ``$``. These constructions are available:
================= ======================================================== ================= ========================================================
``$i`` Matches an integer. This uses ``parseutils.parseInt``. ``$b`` Matches a binary integer. This uses ``parseutils.parseBin``.
``$o`` Matches an octal integer. This uses ``parseutils.parseOct``.
``$i`` Matches a decimal integer. This uses ``parseutils.parseInt``.
``$h`` Matches a hex integer. This uses ``parseutils.parseHex``.
``$f`` Matches a floating pointer number. Uses ``parseFloat``. ``$f`` Matches a floating pointer number. Uses ``parseFloat``.
``$w`` Matches an ASCII identifier: ``[A-Z-a-z_][A-Za-z_0-9]*``. ``$w`` Matches an ASCII identifier: ``[A-Z-a-z_][A-Za-z_0-9]*``.
``$s`` Skips optional whitespace. ``$s`` Skips optional whitespace.
@ -330,19 +333,37 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
conds.add resLen.notZero conds.add resLen.notZero
conds.add resLen conds.add resLen
of 'w': of 'w':
if i < results.len or getType(results[i]).typeKind != ntyString: if i < results.len and getType(results[i]).typeKind == ntyString:
matchBind "parseIdent" matchBind "parseIdent"
else: else:
error("no string var given for $w") error("no string var given for $w")
inc i inc i
of 'b':
if i < results.len and getType(results[i]).typeKind == ntyInt:
matchBind "parseBin"
else:
error("no int var given for $b")
inc i
of 'o':
if i < results.len and getType(results[i]).typeKind == ntyInt:
matchBind "parseOct"
else:
error("no int var given for $o")
inc i
of 'i': of 'i':
if i < results.len or getType(results[i]).typeKind != ntyInt: if i < results.len and getType(results[i]).typeKind == ntyInt:
matchBind "parseInt" matchBind "parseInt"
else: else:
error("no int var given for $d") error("no int var given for $i")
inc i
of 'h':
if i < results.len and getType(results[i]).typeKind == ntyInt:
matchBind "parseHex"
else:
error("no int var given for $h")
inc i inc i
of 'f': of 'f':
if i < results.len or getType(results[i]).typeKind != ntyFloat: if i < results.len and getType(results[i]).typeKind == ntyFloat:
matchBind "parseFloat" matchBind "parseFloat"
else: else:
error("no float var given for $f") error("no float var given for $f")
@ -357,7 +378,7 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
else: else:
error("invalid format string") error("invalid format string")
of '*', '+': of '*', '+':
if i < results.len or getType(results[i]).typeKind != ntyString: if i < results.len and getType(results[i]).typeKind == ntyString:
var min = ord(pattern[p] == '+') var min = ord(pattern[p] == '+')
var q=p+1 var q=p+1
var token = "" var token = ""
@ -441,7 +462,7 @@ template success*(x: int): bool = x != 0
template nxt*(input: string; idx, step: int = 1) = inc(idx, step) template nxt*(input: string; idx, step: int = 1) = inc(idx, step)
macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool = macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
## See top level documentation of his module of how ``scanp`` works. ## ``scanp`` is currently undocumented.
type StmtTriple = tuple[init, cond, action: NimNode] type StmtTriple = tuple[init, cond, action: NimNode]
template interf(x): untyped = bindSym(x, brForceOpen) template interf(x): untyped = bindSym(x, brForceOpen)
@ -645,6 +666,14 @@ when isMainModule:
doAssert intval == 89 doAssert intval == 89
doAssert floatVal == 33.25 doAssert floatVal == 33.25
var binval: int
var octval: int
var hexval: int
doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval)
doAssert binval == 0b0101
doAssert octval == 0o1234
doAssert hexval == 0xabcd
let xx = scanf("$abc", "$$$i", intval) let xx = scanf("$abc", "$$$i", intval)
doAssert xx == false doAssert xx == false

View file

@ -634,7 +634,10 @@ proc getch*(): char =
doAssert(readConsoleInput(fd, addr(keyEvent), 1, addr(numRead)) != 0) doAssert(readConsoleInput(fd, addr(keyEvent), 1, addr(numRead)) != 0)
if numRead == 0 or keyEvent.eventType != 1 or keyEvent.bKeyDown == 0: if numRead == 0 or keyEvent.eventType != 1 or keyEvent.bKeyDown == 0:
continue continue
return char(keyEvent.uChar) if keyEvent.uChar == 0:
return char(keyEvent.wVirtualKeyCode)
else:
return char(keyEvent.uChar)
else: else:
let fd = getFileHandle(stdin) let fd = getFileHandle(stdin)
var oldMode: Termios var oldMode: Termios