diff --git a/vlib/toml/parser/parser.v b/vlib/toml/parser/parser.v index bee10fb440..5e1c771cdf 100644 --- a/vlib/toml/parser/parser.v +++ b/vlib/toml/parser/parser.v @@ -254,10 +254,7 @@ fn (p Parser) check_explicitly_declared(key DottedKey) ? { // See also `find_in_table`. pub fn (mut p Parser) find_table() ?&map[string]ast.Value { util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'locating "$p.root_map_key" in map ${ptr_str(p.root_map)}') - mut t := &map[string]ast.Value{} - unsafe { - t = &p.root_map - } + mut t := unsafe { &p.root_map } if p.root_map_key.len == 0 { return t } @@ -265,6 +262,16 @@ pub fn (mut p Parser) find_table() ?&map[string]ast.Value { return p.find_in_table(mut t, p.root_map_key) } +// allocate_table allocates all tables in "dotted" `key` (`a.b.c`) in the *root* table. +pub fn (mut p Parser) allocate_table(key DottedKey) ? { + util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'allocating "$key" in map ${ptr_str(p.root_map)}') + mut t := unsafe { &p.root_map } + if key.len == 0 { + return + } + p.allocate_in_table(mut t, key) ? +} + // sub_table_key returns the logic parts of a dotted key (`a.b.c`) for // use with the `find_sub_table` method. pub fn (mut p Parser) sub_table_key(key DottedKey) (DottedKey, DottedKey) { @@ -286,10 +293,7 @@ pub fn (mut p Parser) find_sub_table(key DottedKey) ?&map[string]ast.Value { ky = key } util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'locating "$ky" in map ${ptr_str(p.root_map)}') - mut t := &map[string]ast.Value{} - unsafe { - t = &p.root_map - } + mut t := unsafe { &p.root_map } if ky.len == 0 { return t } @@ -306,10 +310,7 @@ pub fn (mut p Parser) find_in_table(mut table map[string]ast.Value, key DottedKe // I'm still not quite sure *exactly* why it works. All I can leave here is a hope // that this kind of minefield someday will be easier in V :) util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'locating "$key" in map ${ptr_str(table)}') - mut t := &map[string]ast.Value{} - unsafe { - t = &table - } + mut t := unsafe { &table } unsafe { for k in key { if val := t[k] { @@ -332,6 +333,30 @@ pub fn (mut p Parser) find_in_table(mut table map[string]ast.Value, key DottedKe return t } +// allocate_in_table allocates all tables in "dotted" `key` (`a.b.c`) in `table`. +pub fn (mut p Parser) allocate_in_table(mut table map[string]ast.Value, key DottedKey) ? { + util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'allocating "$key" in map ${ptr_str(table)}') + mut t := unsafe { &table } + unsafe { + for k in key { + if val := t[k] { + util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'found key "$k" in $t.keys()') + if val is map[string]ast.Value { + t = &(val as map[string]ast.Value) + } else { + return error(@MOD + '.' + @STRUCT + '.' + @FN + + ' "$k" in "$key" is not a map ($val.type_name())') + } + } else { + util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'no key "$k" in "$key" found, allocating new map at key "$k" in map ${ptr_str(t)}"') + t[k] = map[string]ast.Value{} + t = &(t[k] as map[string]ast.Value) + util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'allocated new map ${ptr_str(t)}"') + } + } + } +} + // dotted_key returns a string of the next tokens parsed as // sub/nested/path keys (e.g. `a.b.c`). In TOML, this form of key is referred to as a "dotted" key. pub fn (mut p Parser) dotted_key() ?DottedKey { @@ -476,6 +501,7 @@ pub fn (mut p Parser) root_table() ? { p.ignore_while(parser.space_formatting) util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'setting root map key to `$dotted_key` at "$p.tok.kind" "$p.tok.lit"') p.root_map_key = dotted_key + p.allocate_table(p.root_map_key) ? p.expect(.rsbr) ? p.peek_for_correct_line_ending_or_fail() ? } else { @@ -497,6 +523,7 @@ pub fn (mut p Parser) root_table() ? { util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'setting root map key to `$dotted_key` at "$p.tok.kind" "$p.tok.lit"') p.root_map_key = dotted_key + p.allocate_table(p.root_map_key) ? p.next() ? p.expect(.rsbr) ? p.peek_for_correct_line_ending_or_fail() ? @@ -822,10 +849,7 @@ pub fn (mut p Parser) double_array_of_tables_contents(target_key DottedKey) ?[]a } else { key, val := p.key_value() ? - mut t := &map[string]ast.Value{} - unsafe { - t = &tbl - } + mut t := unsafe { &tbl } if implicit_allocation_key.len > 0 { t = p.find_in_table(mut tbl, implicit_allocation_key) ? } diff --git a/vlib/toml/tests/burntsushi.toml-test_test.v b/vlib/toml/tests/burntsushi.toml-test_test.v index c41ba04e7a..4399544b32 100644 --- a/vlib/toml/tests/burntsushi.toml-test_test.v +++ b/vlib/toml/tests/burntsushi.toml-test_test.v @@ -31,18 +31,8 @@ const ( // Comment 'comment/tricky.toml', // Table - 'table/empty.toml', 'table/array-implicit.toml', - 'table/sub-empty.toml', - 'table/without-super.toml', - 'table/whitespace.toml', 'table/names.toml', - 'table/no-eol.toml', - 'table/keyword.toml', - // Array - 'array/string-quote-comma.toml', - 'array/string-quote-comma-2.toml', - 'array/table-array-string-backslash.toml', // Date-time 'datetime/milliseconds.toml', // Inline-table