Closed gerrymanoim closed 7 years ago
Confirming -- I see the same result. Also try setting verbose=TRUE
to see this:
<default print method>
[[fruit]]
name = "apple"
[fruit.physical]
color = "red"
shape = "round"
[[fruit.variety]]
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"
</default print method>
But look closely at the spec page. I suspect there is a typo -- [[fruit.physical]]
seems more logical for the TOML file. If we do that we get
R> parseToml("/tmp/issue16.toml")
Other: physical
Other: variety
Other: variety
List of 1
$ fruit:Dotted pair list of 2
..$ :List of 3
.. ..$ name: chr "apple"
.. ..$ : chr "physical"
.. ..$ : chr "variety"
..$ :List of 2
.. ..$ name: chr "banana"
.. ..$ : chr "variety"
R>
The problem seems to be having an array of tables inside of another table.
The following works fine:
[[fruit]]
name = "apple"
[[fruit]]
name = "banana"
This breaks:
[[fruit]]
name = "apple"
[[fruit.variety]]
name = "red delicious"
As does this:
[fruit]
name = "apple"
[[fruit.variety]]
name = "red delicious"
The produced JSON on the spec page makes my thing [fruit.physical]
was not a typo, i.e. it shows the output as an object
"physical": {
"color": "red",
"shape": "round"
},
rather than an array of objects.
I was not talking about the produced JSON; that is precisely how I surmised that the shown input is not what was meant. You need double [[ .. ]]
not single.
Sorry - I'm not sure I follow? Though I think this is all separate from the issue here, let me see if I can articulate why I'm confused by what you're saying.
My understanding of that section of the TOML spec is that any [[table]]
will produce a array named table
with the elements being objects in that section.
For the fruit example, which seems to be demonstrating nested tables, I would expect an array named fruit, with fruit objects in it, the first one having a physical
object and an array of objects named variety
(i..e what you see in the JSON). I don't necessarily see why physical needs to be an array of tables. Sure it could be, but the output makes me think it is just a subtable of the first fruit table.
Apologies if there's something obvious I'm missing here.
After just committing one minor fix to quieten one print:
edd@max:~/git/rcpptoml(master)$ cat /tmp/issue16.toml
[[fruit]]
name = "apple"
[[fruit.physical]]
color = "red"
shape = "round"
[[fruit.variety]]
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"
edd@max:~/git/rcpptoml(master)$ r -lRcppTOML -e 'print(parseToml("/tmp/issue16.toml"))'
List of 1
$ fruit:Dotted pair list of 2
..$ :List of 3
.. ..$ name: chr "apple"
.. ..$ : chr "physical"
.. ..$ : chr "variety"
..$ :List of 2
.. ..$ name: chr "banana"
.. ..$ : chr "variety"
edd@max:~/git/rcpptoml(master)$
Note that I altered the TOML file.
But I hear you on the lack of proper nesting / recursion. That may or may not be easy. I'll take a look.
But fruit[[1]][[2]]
and fruit[[1]][[3]]
are still just chrs with value physical
and variety
. There's no way to access "granny smith"?
As I just said:
But I hear you on the lack of proper nesting / recursion.
Ah understood, thanks.
The recursion for the 'TableArray' was simply missing:
edd@max:~/git/rcpptoml(master)$ r -lRcppTOML -e 'print(parseToml("/tmp/issue16.toml"))'
List of 1
$ fruit:Dotted pair list of 2
..$ :List of 3
.. ..$ name : chr "apple"
.. ..$ physical:Dotted pair list of 1
.. .. ..$ :List of 2
.. .. .. ..$ color: chr "red"
.. .. .. ..$ shape: chr "round"
.. ..$ variety :Dotted pair list of 2
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "red delicious"
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "granny smith"
..$ :List of 2
.. ..$ name : chr "banana"
.. ..$ variety:Dotted pair list of 1
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "plantain"
edd@max:~/git/rcpptoml(master)$
Looks better, right?
And if I revert the input to just one [ ]
:
edd@max:~/git/rcpptoml(master)$ r -lRcppTOML -e 'print(parseToml("/tmp/issue16.toml"))'
List of 1
$ fruit:Dotted pair list of 2
..$ :List of 3
.. ..$ name : chr "apple"
.. ..$ physical:List of 2
.. .. ..$ color: chr "red"
.. .. ..$ shape: chr "round"
.. ..$ variety :Dotted pair list of 2
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "red delicious"
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "granny smith"
..$ :List of 2
.. ..$ name : chr "banana"
.. ..$ variety:Dotted pair list of 1
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "plantain"
edd@max:~/git/rcpptoml(master)$
Yep - looks perfect!
Now comitted. Thanks for catching that!
Just out of curiosity, why are the lists sometimes lists and sometimes pairlists? It doesn't seem to make any difference, I'm just curious in terms of the implementation as to why this happens.
In your example above it seems to sometimes come out one way, sometimes another way:
edd@max:~/git/rcpptoml(master)$ r -lRcppTOML -e 'print(parseToml("/tmp/issue16.toml"))'
List of 1
$ fruit:Dotted pair list of 2
..$ :List of 3
.. ..$ name : chr "apple"
.. ..$ physical:Dotted pair list of 1
.. .. ..$ :List of 2
.. .. .. ..$ color: chr "red"
.. .. .. ..$ shape: chr "round"
.. ..$ variety :Dotted pair list of 2
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "red delicious"
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "granny smith"
..$ :List of 2
.. ..$ name : chr "banana"
.. ..$ variety:Dotted pair list of 1
.. .. ..$ :List of 1
.. .. .. ..$ name: chr "plantain"
It may just be a side effect of mixing the Rcpp types StretchyList
and List
....
If you want to dig deeper, could I suggest that you chase that yourself in the code? It's just a few hundred lines, and reasonably good fun to follow. Enabling verbose parse gives you pointers.
Thanks for the pointer, you were exactly right!
I don't know if this is the "right" fix (my C++ knowledge is extremely limited) but making the following two changes in parse.cpp
changed everything to be lists:
diff --git a/src/parse.cpp b/src/parse.cpp
index dd4228d..b7729f4 100644
--- a/src/parse.cpp
+++ b/src/parse.cpp
@@ -252,7 +252,7 @@ SEXP getTable(const std::shared_ptr<cpptoml::table>& t, bool verbose=false) {
l.push_back (getTable(ta, verbose));
++ait;
}
- sl.push_back(Rcpp::Named(p.first) = l);
+ sl.push_back(Rcpp::Named(p.first) = Rcpp::as<Rcpp::List>(l));
} else {
if (verbose) Rcpp::Rcout << "Other: " << p.first << std::endl;
sl.push_back(p.first);
@@ -300,7 +300,7 @@ Rcpp::List tomlparseImpl(const std::string input, bool verbose=false, bool fromf
l.push_back (getTable(ta, verbose));
++ait;
}
- sl.push_back(Rcpp::Named(p.first) = l);
+ sl.push_back(Rcpp::Named(p.first) = Rcpp::as<Rcpp::List>(l));
} else if (p.second->is_table()) {
auto ga = std::dynamic_pointer_cast<cpptoml::table>(p.second);
(END)
Appreciate all the help and the package work. Cheers!
Thanks for working the details out. That is nice and straightforward and I committed this now as https://github.com/eddelbuettel/rcpptoml/commit/7aae502041ab45837c527037700fe88c946175fb
Here's my toml file, taken straight from the spec page:
Using the following code:
I get the following output:
It seems to me that in both situations "variety" doesn't actually seem to be parsed as a list, but instead parsed an an empty character?
Session Info: