diff --git a/sources/ysfx_parse.cpp b/sources/ysfx_parse.cpp index e419f4c..cdb4e77 100644 --- a/sources/ysfx_parse.cpp +++ b/sources/ysfx_parse.cpp @@ -19,6 +19,21 @@ #include "ysfx_utils.hpp" #include #include +#include + +ysfx_section_t* new_or_append(ysfx_section_u §ion, uint32_t line_no) +{ + if (!section) { + section.reset(new ysfx_section_t); + section->line_offset = line_no + 1; + } else { + // We insert blank lines to ensure that the line numbers provided will be correct + std::string::difference_type num_lines = std::count(section->text.begin(), section->text.end(), '\n'); + section->text.append(line_no - section->line_offset - num_lines + 1, '\n'); + } + + return section.get(); +} bool ysfx_parse_toplevel(ysfx::text_reader &reader, ysfx_toplevel_t &toplevel, ysfx_parse_error *error) { @@ -39,20 +54,18 @@ bool ysfx_parse_toplevel(ysfx::text_reader &reader, ysfx_toplevel_t &toplevel, y // a new section starts ysfx::string_list tokens = ysfx::split_strings_noempty(linep, &ysfx::ascii_isspace); - current = new ysfx_section_t; - if (tokens[0] == "@init") - toplevel.init.reset(current); + current = new_or_append(toplevel.init, lineno); else if (tokens[0] == "@slider") - toplevel.slider.reset(current); + current = new_or_append(toplevel.slider, lineno); else if (tokens[0] == "@block") - toplevel.block.reset(current); + current = new_or_append(toplevel.block, lineno); else if (tokens[0] == "@sample") - toplevel.sample.reset(current); + current = new_or_append(toplevel.sample, lineno); else if (tokens[0] == "@serialize") - toplevel.serialize.reset(current); + current = new_or_append(toplevel.serialize, lineno); else if (tokens[0] == "@gfx") { - toplevel.gfx.reset(current); + current = new_or_append(toplevel.gfx, lineno); long gfx_w = 0; long gfx_h = 0; if (tokens.size() > 1) @@ -63,14 +76,12 @@ bool ysfx_parse_toplevel(ysfx::text_reader &reader, ysfx_toplevel_t &toplevel, y toplevel.gfx_h = (gfx_h > 0) ? (uint32_t)gfx_h : 0; } else { - delete current; if (error) { error->line = lineno; error->message = std::string("Invalid section: ") + line; } return false; } - current->line_offset = lineno + 1; } else { current->text.append(line); diff --git a/tests/ysfx_test_parse.cpp b/tests/ysfx_test_parse.cpp index e4abeb2..ba98204 100644 --- a/tests/ysfx_test_parse.cpp +++ b/tests/ysfx_test_parse.cpp @@ -254,6 +254,48 @@ TEST_CASE("section splitting", "[parse]") REQUIRE(toplevel.gfx_w == 0); REQUIRE(toplevel.gfx_h == 0); } + + SECTION("sections more init") + { + const char *text = + "// the header" "\n" + "@init" "\n" + "the init" "\n" + "@slider" "\n" + "the slider, part 1" "\n" + "the slider, part 2" "\n" + "@block" "\n" + "the block" "\n" + "@init" "\n" + "more init!" "\n" + "@block" "\n" + "more block" "\n" + "@init" "\n" + "more?" "\n"; + ysfx::string_text_reader reader(text); + + ysfx_parse_error err; + ysfx_toplevel_t toplevel; + REQUIRE(ysfx_parse_toplevel(reader, toplevel, &err)); + REQUIRE(!err); + + REQUIRE(toplevel.header); + REQUIRE(toplevel.init); + REQUIRE(toplevel.slider); + REQUIRE(toplevel.block); + REQUIRE(!toplevel.sample); + REQUIRE(!toplevel.serialize); + REQUIRE(!toplevel.gfx); + + REQUIRE(toplevel.header->line_offset == 0); + REQUIRE(toplevel.header->text == "// the header" "\n"); + REQUIRE(toplevel.init->line_offset == 2); + REQUIRE(toplevel.init->text == "the init" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "more init!" "\n" "\n" "\n" "\n" "more?" "\n"); + REQUIRE(toplevel.slider->line_offset == 4); + REQUIRE(toplevel.slider->text == "the slider, part 1" "\n" "the slider, part 2" "\n"); + REQUIRE(toplevel.block->line_offset == 7); + REQUIRE(toplevel.block->text == "the block" "\n" "\n" "\n" "\n" "more block" "\n"); + } } //------------------------------------------------------------------------------