diff options
author | bptato <nincsnevem662@gmail.com> | 2023-09-13 17:27:33 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-09-13 17:27:33 +0200 |
commit | 19caa22e7e5006ae32b49ba6250738cfd3781548 (patch) | |
tree | cac1830eaac0879bc38fd61e09ca6c8e972d4caa /src | |
parent | 02227d9c73c25cebf17d86ebc5d8468494093a16 (diff) | |
download | chawan-19caa22e7e5006ae32b49ba6250738cfd3781548.tar.gz |
toml: add support for hex/octal numbers
Diffstat (limited to 'src')
-rw-r--r-- | src/config/toml.nim | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/src/config/toml.nim b/src/config/toml.nim index 92520045..4fcf6d9b 100644 --- a/src/config/toml.nim +++ b/src/config/toml.nim @@ -353,30 +353,51 @@ proc consumeNoState(state: var TomlParser): Result[bool, TomlError] = else: return state.err("invalid character before key: " & c) return state.err("unexpected end of file") +type ParsedNumberType = enum + NUMBER_INTEGER, NUMBER_FLOAT, NUMBER_HEX, NUMBER_OCT + proc consumeNumber(state: var TomlParser, c: char): TomlResult = var repr = $c - var isfloat = false + var numType = NUMBER_INTEGER if state.has(): if state.peek(0) == '+' or state.peek(0) == '-': repr &= state.consume() + elif state.peek(0) == '0' and state.has(1): + let c = state.peek(1) + if c == 'x': + numType = NUMBER_HEX + elif c == 'o': + numType = NUMBER_OCT if not state.has() or not isDigit(state.peek(0)): return state.err("invalid number") - while state.has() and isDigit(state.peek(0)): - repr &= state.consume() + var was_num = true + while state.has(): + if isDigit(state.peek(0)): + repr &= state.consume() + was_num = true + elif was_num and state.peek(0) == '_': + was_num = false + repr &= '_' + else: + break if state.has(1): if state.peek(0) == '.' and isDigit(state.peek(1)): repr &= state.consume() repr &= state.consume() - isfloat = true + if numType notin {NUMBER_INTEGER, NUMBER_FLOAT}: + return state.err("invalid floating point number") + numType = NUMBER_FLOAT while state.has() and isDigit(state.peek(0)): repr &= state.consume() if state.has(1): if state.peek(0) == 'E' or state.peek(0) == 'e': - isfloat = true + if numType notin {NUMBER_INTEGER, NUMBER_FLOAT}: + return state.err("invalid floating point number") + numType = NUMBER_FLOAT var j = 2 if state.peek(1) == '-' or state.peek(1) == '+': inc j @@ -388,13 +409,28 @@ proc consumeNumber(state: var TomlParser, c: char): TomlResult = while state.has() and isDigit(state.peek(0)): repr &= state.consume() - if isfloat: + case numType + of NUMBER_INTEGER: + let val = parseInt64(repr) + if not val.isSome: + return state.err("invalid integer") + return ok(TomlValue(vt: VALUE_INTEGER, i: val.get)) + of NUMBER_HEX: + try: + let val = parseHexInt(repr) + return ok(TomlValue(vt: VALUE_INTEGER, i: val)) + except ValueError: + return state.err("invalid hexadecimal number") + of NUMBER_OCT: + try: + let val = parseOctInt(repr) + return ok(TomlValue(vt: VALUE_INTEGER, i:val)) + except ValueError: + return state.err("invalid octal number") + of NUMBER_FLOAT: let val = parseFloat64(repr) return ok(TomlValue(vt: VALUE_FLOAT, f: val)) - let val = parseInt64(repr) - return ok(TomlValue(vt: VALUE_INTEGER, i: val.get)) - proc consumeValue(state: var TomlParser): TomlResult proc consumeArray(state: var TomlParser): TomlResult = |