toml: fix, test and optimize `nan` and `inf` values (#12592)

pull/12593/head
Larpon 2021-11-27 20:26:28 +01:00 committed by GitHub
parent 22043f2df1
commit 1d8ece7ac0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 26 deletions

View File

@ -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 {

View File

@ -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)
}

View File

@ -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',

View File

@ -0,0 +1 @@
iarna/toml-test/

View File

@ -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
}