toml: fix, test and optimize `nan` and `inf` values (#12592)
parent
22043f2df1
commit
1d8ece7ac0
|
@ -1232,13 +1232,9 @@ pub fn (mut p Parser) dotted_key_value() ?(DottedKey, ast.Value) {
|
|||
// value parse and returns an `ast.Value` type.
|
||||
// values are the token(s) appearing after an assignment operator (=).
|
||||
pub fn (mut p Parser) value() ?ast.Value {
|
||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing value...')
|
||||
// println('parsed comment "${p.tok.lit}"')
|
||||
|
||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing value from token "$p.tok.kind" "$p.tok.lit"...')
|
||||
mut value := ast.Value(ast.Null{})
|
||||
|
||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing token "$p.tok.kind" "$p.tok.lit"')
|
||||
// mut value := ast.Value{}
|
||||
if p.tok.kind == .number {
|
||||
number_or_date := p.number_or_date() ?
|
||||
value = number_or_date
|
||||
|
@ -1257,7 +1253,6 @@ pub fn (mut p Parser) value() ?ast.Value {
|
|||
p.ignore_while(parser.space_formatting)
|
||||
mut t := map[string]ast.Value{}
|
||||
p.inline_table(mut t) ?
|
||||
// table[key_str] = ast.Value(t)
|
||||
ast.Value(t)
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -93,22 +93,23 @@ pub fn (mut s Scanner) scan() ?token.Token {
|
|||
ascii := byte_c.ascii_str()
|
||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'current char "$ascii"')
|
||||
|
||||
is_sign := byte_c in [`+`, `-`]
|
||||
is_signed_number := is_sign && byte(s.at()).is_digit() && !byte(s.peek(-1)).is_digit()
|
||||
is_sign := c == `+` || c == `-`
|
||||
|
||||
// (+/-)nan & (+/-)inf
|
||||
is_nan := byte_c == `n` && s.at() == `a` && s.peek(1) == `n` && s.peek(2) == `\n`
|
||||
is_inf := byte_c == `i` && s.at() == `n` && s.peek(1) == `f` && s.peek(2) == `\n`
|
||||
is_signed_nan := is_sign && s.at() == `n` && s.peek(1) == `a` && s.peek(2) == `n`
|
||||
&& s.peek(3) == `\n`
|
||||
is_signed_inf := is_sign && s.at() == `i` && s.peek(1) == `n` && s.peek(2) == `f`
|
||||
&& s.peek(3) == `\n`
|
||||
if is_nan || is_inf || is_signed_nan || is_signed_inf {
|
||||
peek_1 := s.peek(1)
|
||||
peek_2 := s.peek(2)
|
||||
is_nan := c == `n` && s.at() == `a` && peek_1 == `n`
|
||||
is_inf := !is_nan && c == `i` && s.at() == `n` && peek_1 == `f`
|
||||
is_signed_nan := is_sign && s.at() == `n` && peek_1 == `a` && peek_2 == `n`
|
||||
is_signed_inf := !is_signed_nan && is_sign && s.at() == `i` && peek_1 == `n`
|
||||
&& peek_2 == `f`
|
||||
if !s.is_left_of_assign && (is_nan || is_inf || is_signed_nan || is_signed_inf) {
|
||||
num := s.extract_nan_or_inf_number() ?
|
||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'identified a special number "$num" ($num.len)')
|
||||
return s.new_token(.number, num, num.len)
|
||||
}
|
||||
|
||||
is_signed_number := is_sign && byte(s.at()).is_digit() && !byte(s.peek(-1)).is_digit()
|
||||
is_digit := byte_c.is_digit()
|
||||
if is_digit || is_signed_number {
|
||||
num := s.extract_number() ?
|
||||
|
@ -118,7 +119,8 @@ pub fn (mut s Scanner) scan() ?token.Token {
|
|||
|
||||
if util.is_key_char(byte_c) {
|
||||
key := s.extract_key()
|
||||
if key.to_lower() in ['true', 'false'] {
|
||||
key_lower_case := key.to_lower()
|
||||
if key_lower_case == 'true' || key_lower_case == 'false' {
|
||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'identified a boolean "$key" ($key.len)')
|
||||
return s.new_token(.boolean, key, key.len)
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ import x.json2
|
|||
|
||||
// Instructions for developers:
|
||||
// The actual tests and data can be obtained by doing:
|
||||
// `cd vlib/toml/tests/testdata`
|
||||
// `git clone --depth 1 https://github.com/iarna/toml-spec-tests.git iarna/toml-test`
|
||||
// `git clone --depth 1 https://github.com/iarna/toml-spec-tests.git vlib/toml/tests/testdata/iarna/toml-test`
|
||||
// See also the CI toml tests
|
||||
const (
|
||||
// Can be set to `true` to skip tests that stress test the parser
|
||||
|
@ -14,14 +13,7 @@ const (
|
|||
skip_large_files = false
|
||||
|
||||
// Kept for easier handling of future updates to the tests
|
||||
valid_exceptions = [
|
||||
'values/spec-float-10.toml',
|
||||
'values/spec-float-11.toml',
|
||||
'values/spec-float-12.toml',
|
||||
'values/spec-float-13.toml',
|
||||
'values/spec-float-14.toml',
|
||||
'values/spec-float-15.toml',
|
||||
]
|
||||
valid_exceptions = []string{}
|
||||
invalid_exceptions = [
|
||||
'errors/table-3.toml',
|
||||
'errors/table-4.toml',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
iarna/toml-test/
|
|
@ -1,4 +1,5 @@
|
|||
import toml
|
||||
import strconv
|
||||
|
||||
fn test_string() {
|
||||
str_value := 'test string'
|
||||
|
@ -90,3 +91,33 @@ test = 42
|
|||
assert value as i64 == 42
|
||||
assert value.i64() == 42
|
||||
}
|
||||
|
||||
fn test_nan_and_inf_values() {
|
||||
mut toml_doc := toml.parse('nan = nan') or { panic(err) }
|
||||
mut value := toml_doc.value('nan')
|
||||
assert value.string() == 'nan'
|
||||
|
||||
toml_doc = toml.parse('nan = nan#comment') or { panic(err) }
|
||||
value = toml_doc.value('nan')
|
||||
assert value.string() == 'nan'
|
||||
|
||||
toml_doc = toml.parse('nan = -nan') or { panic(err) }
|
||||
value = toml_doc.value('nan')
|
||||
assert value.string() == 'nan'
|
||||
|
||||
toml_doc = toml.parse('nan = +nan') or { panic(err) }
|
||||
value = toml_doc.value('nan')
|
||||
assert value.string() == 'nan'
|
||||
|
||||
toml_doc = toml.parse('inf = inf') or { panic(err) }
|
||||
value = toml_doc.value('inf')
|
||||
assert value.u64() == strconv.double_plus_infinity
|
||||
|
||||
toml_doc = toml.parse('inf = +inf') or { panic(err) }
|
||||
value = toml_doc.value('inf')
|
||||
assert value.u64() == strconv.double_plus_infinity
|
||||
|
||||
toml_doc = toml.parse('inf = -inf') or { panic(err) }
|
||||
value = toml_doc.value('inf')
|
||||
assert value.u64() == strconv.double_minus_infinity
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue