Skip to content

Commit

Permalink
Fixed parse error on flow containers containing child flow containers (
Browse files Browse the repository at this point in the history
  • Loading branch information
fktn-k committed May 19, 2024
1 parent b2a2fe3 commit e3c34b1
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 48 deletions.
40 changes: 16 additions & 24 deletions include/fkYAML/detail/input/deserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,25 +455,21 @@ class basic_deserializer {
mp_current_node = m_context_stack.back().p_node;
break;
}
case lexical_token_t::SEQUENCE_FLOW_BEGIN: {
bool is_more_nested_in_block = m_flow_context_depth++ == 0 && m_context_stack.back().indent < indent;
if (is_more_nested_in_block) {
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::sequence());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
}
else {
*mp_current_node = node_type::sequence();
}
case lexical_token_t::SEQUENCE_FLOW_BEGIN:
++m_flow_context_depth;
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::sequence());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_SEQUENCE, mp_current_node);
}
else {
*mp_current_node = node_type::sequence();
parse_context& last_context = m_context_stack.back();
last_context.state = context_state_t::FLOW_SEQUENCE;
}
apply_directive_set(*mp_current_node);
apply_node_properties(*mp_current_node);
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_SEQUENCE, mp_current_node);
break;
}
case lexical_token_t::SEQUENCE_FLOW_END: {
--m_flow_context_depth;

Expand All @@ -499,25 +495,21 @@ class basic_deserializer {
}
break;
}
case lexical_token_t::MAPPING_FLOW_BEGIN: {
bool is_more_nested_in_block = m_flow_context_depth++ == 0 && m_context_stack.back().indent < indent;
if (is_more_nested_in_block) {
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::mapping());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
}
else {
*mp_current_node = node_type::mapping();
}
case lexical_token_t::MAPPING_FLOW_BEGIN:
++m_flow_context_depth;
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::mapping());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_MAPPING, mp_current_node);
}
else {
*mp_current_node = node_type::mapping();
parse_context& last_context = m_context_stack.back();
last_context.state = context_state_t::FLOW_MAPPING;
}
apply_directive_set(*mp_current_node);
apply_node_properties(*mp_current_node);
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_MAPPING, mp_current_node);
break;
}
case lexical_token_t::MAPPING_FLOW_END: {
--m_flow_context_depth;

Expand Down
40 changes: 16 additions & 24 deletions single_include/fkYAML/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4664,25 +4664,21 @@ class basic_deserializer {
mp_current_node = m_context_stack.back().p_node;
break;
}
case lexical_token_t::SEQUENCE_FLOW_BEGIN: {
bool is_more_nested_in_block = m_flow_context_depth++ == 0 && m_context_stack.back().indent < indent;
if (is_more_nested_in_block) {
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::sequence());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
}
else {
*mp_current_node = node_type::sequence();
}
case lexical_token_t::SEQUENCE_FLOW_BEGIN:
++m_flow_context_depth;
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::sequence());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_SEQUENCE, mp_current_node);
}
else {
*mp_current_node = node_type::sequence();
parse_context& last_context = m_context_stack.back();
last_context.state = context_state_t::FLOW_SEQUENCE;
}
apply_directive_set(*mp_current_node);
apply_node_properties(*mp_current_node);
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_SEQUENCE, mp_current_node);
break;
}
case lexical_token_t::SEQUENCE_FLOW_END: {
--m_flow_context_depth;

Expand All @@ -4708,25 +4704,21 @@ class basic_deserializer {
}
break;
}
case lexical_token_t::MAPPING_FLOW_BEGIN: {
bool is_more_nested_in_block = m_flow_context_depth++ == 0 && m_context_stack.back().indent < indent;
if (is_more_nested_in_block) {
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::mapping());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
}
else {
*mp_current_node = node_type::mapping();
}
case lexical_token_t::MAPPING_FLOW_BEGIN:
++m_flow_context_depth;
if (mp_current_node->is_sequence()) {
mp_current_node->template get_value_ref<sequence_type&>().emplace_back(node_type::mapping());
mp_current_node = &(mp_current_node->template get_value_ref<sequence_type&>().back());
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_MAPPING, mp_current_node);
}
else {
*mp_current_node = node_type::mapping();
parse_context& last_context = m_context_stack.back();
last_context.state = context_state_t::FLOW_MAPPING;
}
apply_directive_set(*mp_current_node);
apply_node_properties(*mp_current_node);
m_context_stack.emplace_back(line, indent, context_state_t::FLOW_MAPPING, mp_current_node);
break;
}
case lexical_token_t::MAPPING_FLOW_END: {
--m_flow_context_depth;

Expand Down
176 changes: 176 additions & 0 deletions test/unit_test/test_deserializer_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,92 @@ TEST_CASE("Deserializer_FlowSequence") {
REQUIRE(root_2_node.is_float_number());
REQUIRE(root_2_node.get_value<double>() == 3.14);
}

SECTION("root flow sequence with nested flow sequences") {
std::string input = "[\n"
" [\n"
" \"a\",\n"
" \"b\"\n"
" ],\n"
" [\n"
" 123,\n"
" true\n"
" ]\n"
"]";
REQUIRE_NOTHROW(root = deserializer.deserialize(fkyaml::detail::input_adapter(input)));

REQUIRE(root.is_sequence());
REQUIRE(root.size() == 2);

fkyaml::node& root_0_node = root[0];
REQUIRE(root_0_node.is_sequence());
REQUIRE(root_0_node.size() == 2);

fkyaml::node& root_0_0_node = root_0_node[0];
REQUIRE(root_0_0_node.is_string());
REQUIRE(root_0_0_node.get_value_ref<std::string&>() == "a");

fkyaml::node& root_0_1_node = root_0_node[1];
REQUIRE(root_0_1_node.is_string());
REQUIRE(root_0_1_node.get_value_ref<std::string&>() == "b");

fkyaml::node& root_1_node = root[1];
REQUIRE(root_1_node.is_sequence());
REQUIRE(root_1_node.size() == 2);

fkyaml::node& root_1_0_node = root_1_node[0];
REQUIRE(root_1_0_node.is_integer());
REQUIRE(root_1_0_node.get_value<int>() == 123);

fkyaml::node& root_1_1_node = root_1_node[1];
REQUIRE(root_1_1_node.is_boolean());
REQUIRE(root_1_1_node.get_value<bool>() == true);
}

SECTION("root flow sequence with nested flow mappings") {
std::string input = "[\n"
" {\n"
" true: 1.23,\n"
" null: 123\n"
" },\n"
" {\n"
" \"a\": foo,\n"
" \"b\": bar\n"
" }\n"
"]";
REQUIRE_NOTHROW(root = deserializer.deserialize(fkyaml::detail::input_adapter(input)));

REQUIRE(root.is_sequence());
REQUIRE(root.size() == 2);

fkyaml::node& root_0_node = root[0];
REQUIRE(root_0_node.is_mapping());
REQUIRE(root_0_node.size() == 2);
REQUIRE(root_0_node.contains(true));
REQUIRE(root_0_node.contains(nullptr));

fkyaml::node& root_0_true_node = root_0_node[true];
REQUIRE(root_0_true_node.is_float_number());
REQUIRE(root_0_true_node.get_value<double>() == 1.23);

fkyaml::node& root_0_null_node = root_0_node[nullptr];
REQUIRE(root_0_null_node.is_integer());
REQUIRE(root_0_null_node.get_value<int>() == 123);

fkyaml::node& root_1_node = root[1];
REQUIRE(root_1_node.is_mapping());
REQUIRE(root_1_node.size() == 2);
REQUIRE(root_1_node.contains("a"));
REQUIRE(root_1_node.contains("b"));

fkyaml::node& root_1_a_node = root_1_node["a"];
REQUIRE(root_1_a_node.is_string());
REQUIRE(root_1_a_node.get_value_ref<std::string&>() == "foo");

fkyaml::node& root_1_b_node = root_1_node["b"];
REQUIRE(root_1_b_node.is_string());
REQUIRE(root_1_b_node.get_value_ref<std::string&>() == "bar");
}
}

TEST_CASE("Deserializer_FlowMapping") {
Expand Down Expand Up @@ -1256,6 +1342,96 @@ TEST_CASE("Deserializer_FlowMapping") {
REQUIRE(true_node.is_float_number());
REQUIRE(true_node.get_value<double>() == 3.14);
}

SECTION("root flow mapping with nested flow sequences") {
std::string input = "{\n"
" \"a\": [\n"
" \"a\",\n"
" \"b\"\n"
" ],\n"
" \"b\": [\n"
" 123,\n"
" true\n"
" ]\n"
"}";
REQUIRE_NOTHROW(root = deserializer.deserialize(fkyaml::detail::input_adapter(input)));

REQUIRE(root.is_mapping());
REQUIRE(root.size() == 2);
REQUIRE(root.contains("a"));
REQUIRE(root.contains("b"));

fkyaml::node& root_a_node = root["a"];
REQUIRE(root_a_node.is_sequence());
REQUIRE(root_a_node.size() == 2);

fkyaml::node& root_a_0_node = root_a_node[0];
REQUIRE(root_a_0_node.is_string());
REQUIRE(root_a_0_node.get_value_ref<std::string&>() == "a");

fkyaml::node& root_a_1_node = root_a_node[1];
REQUIRE(root_a_1_node.is_string());
REQUIRE(root_a_1_node.get_value_ref<std::string&>() == "b");

fkyaml::node& root_b_node = root["b"];
REQUIRE(root_b_node.is_sequence());
REQUIRE(root_b_node.size() == 2);

fkyaml::node& root_b_0_node = root_b_node[0];
REQUIRE(root_b_0_node.is_integer());
REQUIRE(root_b_0_node.get_value<int>() == 123);

fkyaml::node& root_b_1_node = root_b_node[1];
REQUIRE(root_b_1_node.is_boolean());
REQUIRE(root_b_1_node.get_value<bool>() == true);
}

SECTION("root flow mapping with nested flow mappings") {
std::string input = "{\n"
" \"a\": {\n"
" true: 1.23,\n"
" null: 123\n"
" },\n"
" \"b\": {\n"
" \"a\": foo,\n"
" \"b\": bar\n"
" }\n"
"}";
REQUIRE_NOTHROW(root = deserializer.deserialize(fkyaml::detail::input_adapter(input)));

REQUIRE(root.is_mapping());
REQUIRE(root.size() == 2);
REQUIRE(root.contains("a"));
REQUIRE(root.contains("b"));

fkyaml::node& root_a_node = root["a"];
REQUIRE(root_a_node.is_mapping());
REQUIRE(root_a_node.size() == 2);
REQUIRE(root_a_node.contains(true));
REQUIRE(root_a_node.contains(nullptr));

fkyaml::node& root_a_true_node = root_a_node[true];
REQUIRE(root_a_true_node.is_float_number());
REQUIRE(root_a_true_node.get_value<double>() == 1.23);

fkyaml::node& root_a_null_node = root_a_node[nullptr];
REQUIRE(root_a_null_node.is_integer());
REQUIRE(root_a_null_node.get_value<int>() == 123);

fkyaml::node& root_b_node = root["b"];
REQUIRE(root_b_node.is_mapping());
REQUIRE(root_b_node.size() == 2);
REQUIRE(root_b_node.contains("a"));
REQUIRE(root_b_node.contains("b"));

fkyaml::node& root_a_a_node = root_b_node["a"];
REQUIRE(root_a_a_node.is_string());
REQUIRE(root_a_a_node.get_value_ref<std::string&>() == "foo");

fkyaml::node& root_b_b_node = root_b_node["b"];
REQUIRE(root_b_b_node.is_string());
REQUIRE(root_b_b_node.get_value_ref<std::string&>() == "bar");
}
}

TEST_CASE("Deserializer_InputWithComment") {
Expand Down

0 comments on commit e3c34b1

Please sign in to comment.