Add raw floats and doubles to parser

This commit is contained in:
Emery Hemingway 2023-12-20 11:45:00 +02:00
parent 82631b1a01
commit dbe9f3566f
3 changed files with 33 additions and 12 deletions

View File

@ -1,6 +1,6 @@
# Package
version = "20231219"
version = "20231220"
author = "Emery Hemingway"
description = "data model and serialization format"
license = "Unlicense"

View File

@ -9,6 +9,8 @@ when defined(nimHasUsed): {.used.}
grammar "Preserves":
ws <- *(' ' | '\t' | '\r' | '\n' | ',')
Document <- Value * ws * !1
Value <-
@ -18,7 +20,7 @@ grammar "Preserves":
Collection <- Sequence | Dictionary | Set
Atom <- Boolean | Float | Double | SignedInteger | String | ByteString | Symbol
Atom <- Boolean | Float | Double | FloatRaw | DoubleRaw | SignedInteger | String | ByteString | Symbol
Record <- '<' * Value * *Value * ws * '>'
@ -30,29 +32,28 @@ grammar "Preserves":
Boolean <- "#f" | "#t"
Float <- >flt * 'f'
Double <- flt
SignedInteger <- int
nat <- '0' | (Digit-'0') * *Digit
int <- ?'-' * nat
frac <- '.' * +Digit
exp <- 'e' * ?('-'|'+') * +Digit
flt <- int * ((frac * exp) | frac | exp)
Float <- >flt * 'f'
Double <- flt
SignedInteger <- int
char <- unescaped | '|' | (escape * (escaped | '"' | ('u' * Xdigit[4])))
String <- '"' * >(*char) * '"'
ByteString <- charByteString | hexByteString | b64ByteString
charByteString <- "#\"" * >(*binchar) * '"'
hexByteString <- "#x\"" * ws * >(*(Xdigit[2] * ws)) * '"'
b64ByteString <- "#[" * ws * >(*(base64char * ws)) * ']'
hexByteString <- "#x\"" * >(*(ws * Xdigit[2])) * ws * '"'
base64char <- {'A'..'Z', 'a'..'z', '0'..'9', '+', '/', '-', '_', '='}
b64ByteString <- "#[" * >(*(ws * base64char)) * ws * ']'
binchar <- binunescaped | (escape * (escaped | '"' | ('x' * Xdigit[2])))
binunescaped <- {' '..'!', '#'..'[', ']'..'~'}
base64char <- {'A'..'Z', 'a'..'z', '0'..'9', '+', '/', '-', '_', '='}
Symbol <- >(symstart * *symcont) | ('|' * >(*symchar) * '|')
symstart <- Alpha | sympunct | symustart
symcont <- Alpha | sympunct | symustart | symucont | Digit | '-'
@ -61,6 +62,7 @@ grammar "Preserves":
symustart <- utf8.any - {0..127}
symucont <- utf8.any - {0..127}
# TODO: exclude some unicode ranges
Symbol <- >(symstart * *symcont) | ('|' * >(*symchar) * '|')
Embedded <- "#!" * Value
@ -73,4 +75,5 @@ grammar "Preserves":
escaped <- {'\\', '/', 'b', 'f', 'n', 'r', 't'}
escape <- '\\'
ws <- *(' ' | '\t' | '\r' | '\n' | ',')
FloatRaw <- "#xf\"" * >((ws * Xdigit[2])[4]) * ws * '"'
DoubleRaw <- "#xd\"" * >((ws * Xdigit[2])[8]) * ws * '"'

View File

@ -74,6 +74,14 @@ template unescape(buf: var seq[byte]; capture: string) =
add(buf, byte capture[i])
inc(i)
proc pushHexNibble[T](result: var T; c: char) =
var n = case c
of '0'..'9': T(ord(c) - ord('0'))
of 'a'..'f': T(ord(c) - ord('a') + 10)
of 'A'..'F': T(ord(c) - ord('A') + 10)
else: 0
result = (result shl 4) or n
proc parsePreserves*(text: string): Preserve[void] =
## Parse a text-encoded Preserves `string` to a `Preserve` value.
runnableExamples:
@ -138,6 +146,16 @@ proc parsePreserves*(text: string): Preserve[void] =
let i = stack.high
discard parseBiggestFloat($0, stack[i].value.double)
Preserves.FloatRaw <- Preserves.FloatRaw:
var reg: uint32
for c in $1: pushHexNibble(reg, c)
pushStack Value(kind: pkFloat, float: cast[float32](reg))
Preserves.DoubleRaw <- Preserves.DoubleRaw:
var reg: uint64
for c in $1: pushHexNibble(reg, c)
pushStack Value(kind: pkDouble, double: cast[float64](reg))
Preserves.SignedInteger <- Preserves.SignedInteger:
pushStack Value(kind: pkSignedInteger, int: parseInt($0))