toml: support multi-level map keys in arrays-of-tables (#12641)
parent
ebfacca252
commit
5ab91dd471
|
@ -575,8 +575,8 @@ pub fn (mut p Parser) root_table() ? {
|
||||||
//
|
//
|
||||||
// `table.key` now shape shifts into being a *double array of tables* key...
|
// `table.key` now shape shifts into being a *double array of tables* key...
|
||||||
// ... but with a different set of rules - making it hard to reuse the code we already have for that ...
|
// ... but with a different set of rules - making it hard to reuse the code we already have for that ...
|
||||||
// See `testdata/array_of_tables_edge_case_1_test.toml` for the type of construct parsed.
|
// See `testdata/array_of_tables_edge_case_<N>_test.toml` for the type of constructs parsed.
|
||||||
if p.last_aot.len == 1 && dotted_key.len == 2
|
if p.last_aot.len == 1 && dotted_key.len > 1
|
||||||
&& dotted_key[0] == p.last_aot.str() {
|
&& dotted_key[0] == p.last_aot.str() {
|
||||||
// Disallow re-declaring the key
|
// Disallow re-declaring the key
|
||||||
p.check_explicitly_declared_array_of_tables(dotted_key) ?
|
p.check_explicitly_declared_array_of_tables(dotted_key) ?
|
||||||
|
@ -589,7 +589,20 @@ pub fn (mut p Parser) root_table() ? {
|
||||||
p.table_contents(mut m) ?
|
p.table_contents(mut m) ?
|
||||||
unsafe {
|
unsafe {
|
||||||
mut mut_val := &val
|
mut mut_val := &val
|
||||||
mut_val[dotted_key[1].str()] = m
|
if dotted_key.len == 2 {
|
||||||
|
// [table.key]
|
||||||
|
mut_val[dotted_key[1].str()] = m
|
||||||
|
} else {
|
||||||
|
// [table.key.key.etc]
|
||||||
|
mut dotted_key_copy := dotted_key.clone()
|
||||||
|
dotted_key_copy.delete(0)
|
||||||
|
new_key := todo_msvc_astring2dkey(dotted_key_copy)
|
||||||
|
sub_table, key := p.sub_table_key(new_key)
|
||||||
|
t := p.find_in_table(mut mut_val, sub_table) ?
|
||||||
|
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN,
|
||||||
|
'setting "$key" = $val in table ${ptr_str(t)}')
|
||||||
|
t[new_key.last().str()] = m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return error(@MOD + '.' + @STRUCT + '.' + @FN +
|
return error(@MOD + '.' + @STRUCT + '.' + @FN +
|
||||||
|
@ -606,6 +619,7 @@ pub fn (mut p Parser) root_table() ? {
|
||||||
p.check_implicitly_declared(dotted_key) ?
|
p.check_implicitly_declared(dotted_key) ?
|
||||||
|
|
||||||
p.ignore_while(parser.space_formatting)
|
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"')
|
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.root_map_key = dotted_key
|
||||||
p.allocate_table(p.root_map_key) ?
|
p.allocate_table(p.root_map_key) ?
|
||||||
|
@ -628,6 +642,9 @@ pub fn (mut p Parser) root_table() ? {
|
||||||
' key `$dotted_key` has already been explicitly declared. Unexpected redeclaration at "$p.tok.kind" "$p.tok.lit" in this (excerpt): "...${p.excerpt()}..."')
|
' key `$dotted_key` has already been explicitly declared. Unexpected redeclaration at "$p.tok.kind" "$p.tok.lit" in this (excerpt): "...${p.excerpt()}..."')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow [ key ]
|
||||||
|
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"')
|
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.root_map_key = dotted_key
|
||||||
p.allocate_table(p.root_map_key) ?
|
p.allocate_table(p.root_map_key) ?
|
||||||
|
@ -805,6 +822,7 @@ pub fn (mut p Parser) array_of_tables(mut table map[string]ast.Value) ? {
|
||||||
// NOTE this is starting to get ugly. TOML isn't simple at this point
|
// NOTE this is starting to get ugly. TOML isn't simple at this point
|
||||||
p.check(.lsbr) ? // '[' bracket
|
p.check(.lsbr) ? // '[' bracket
|
||||||
|
|
||||||
|
// Allow [[ key]]
|
||||||
p.ignore_while(parser.space_formatting)
|
p.ignore_while(parser.space_formatting)
|
||||||
peek_tok, _ := p.peek_over(1, parser.space_formatting) ?
|
peek_tok, _ := p.peek_over(1, parser.space_formatting) ?
|
||||||
p.ignore_while(parser.space_formatting)
|
p.ignore_while(parser.space_formatting)
|
||||||
|
@ -817,6 +835,10 @@ pub fn (mut p Parser) array_of_tables(mut table map[string]ast.Value) ? {
|
||||||
|
|
||||||
key := p.key() ?
|
key := p.key() ?
|
||||||
p.next() ?
|
p.next() ?
|
||||||
|
|
||||||
|
// Allow [[key ]]
|
||||||
|
p.ignore_while(parser.space_formatting)
|
||||||
|
|
||||||
p.check(.rsbr) ?
|
p.check(.rsbr) ?
|
||||||
p.peek_for_correct_line_ending_or_fail() ?
|
p.peek_for_correct_line_ending_or_fail() ?
|
||||||
p.expect(.rsbr) ?
|
p.expect(.rsbr) ?
|
||||||
|
|
|
@ -13,7 +13,6 @@ const (
|
||||||
'valid/example-v0.3.0.toml',
|
'valid/example-v0.3.0.toml',
|
||||||
'valid/example-v0.4.0.toml',
|
'valid/example-v0.4.0.toml',
|
||||||
'valid/datetime-truncate.toml', // Not considered valid since RFC 3339 doesn't permit > 6 ms digits ??
|
'valid/datetime-truncate.toml', // Not considered valid since RFC 3339 doesn't permit > 6 ms digits ??
|
||||||
'valid/table-array-nest-no-keys.toml',
|
|
||||||
]
|
]
|
||||||
invalid_exceptions = [
|
invalid_exceptions = [
|
||||||
'invalid/string-bad-line-ending-escape.toml',
|
'invalid/string-bad-line-ending-escape.toml',
|
||||||
|
@ -31,6 +30,7 @@ const (
|
||||||
'valid/table-array-many.toml',
|
'valid/table-array-many.toml',
|
||||||
'valid/table-array-one.toml',
|
'valid/table-array-one.toml',
|
||||||
'valid/table-array-nest.toml',
|
'valid/table-array-nest.toml',
|
||||||
|
'valid/table-array-nest-no-keys.toml',
|
||||||
]
|
]
|
||||||
|
|
||||||
jq = os.find_abs_path_of_executable('jq') or { '' }
|
jq = os.find_abs_path_of_executable('jq') or { '' }
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import os
|
||||||
|
import toml
|
||||||
|
import toml.to
|
||||||
|
|
||||||
|
fn test_array_of_tables_edge_case_file() {
|
||||||
|
toml_file :=
|
||||||
|
os.real_path(os.join_path(os.dir(@FILE), 'testdata', os.file_name(@FILE).all_before_last('.'))) +
|
||||||
|
'.toml'
|
||||||
|
toml_doc := toml.parse(toml_file) or { panic(err) }
|
||||||
|
|
||||||
|
toml_json := to.json(toml_doc)
|
||||||
|
out_file :=
|
||||||
|
os.real_path(os.join_path(os.dir(@FILE), 'testdata', os.file_name(@FILE).all_before_last('.'))) +
|
||||||
|
'.out'
|
||||||
|
out_file_json := os.read_file(out_file) or { panic(err) }
|
||||||
|
println(toml_json)
|
||||||
|
assert toml_json == out_file_json
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
{ "albums": [ { "songs": [ { }, { } ] } ], "artists": [ { "home": { "address": { } } } ] }
|
|
@ -0,0 +1,6 @@
|
||||||
|
[[ albums ]]
|
||||||
|
[[ albums.songs ]]
|
||||||
|
[[ albums.songs ]]
|
||||||
|
|
||||||
|
[[ artists ]]
|
||||||
|
[ artists.home.address ]
|
Loading…
Reference in New Issue