From 900f118f9483430d2fb0c27c9ceba06485b50b17 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 23 Jul 2026 19:59:31 +0300 Subject: [PATCH 1/2] feat: verbose error messages for parsing functions --- src/coders/commons.cpp | 4 ++++ src/coders/commons.hpp | 2 ++ src/coders/xml.cpp | 18 +++++++++++++++--- src/logic/scripting/lua/libs/libjson.cpp | 9 +++++++-- src/logic/scripting/lua/libs/libtoml.cpp | 9 +++++++-- src/logic/scripting/lua/libs/libxml.cpp | 23 ++++++++++++++++------- src/logic/scripting/lua/libs/libyaml.cpp | 9 +++++++-- 7 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/coders/commons.cpp b/src/coders/commons.cpp index 273f74f51..aeba0c851 100644 --- a/src/coders/commons.cpp +++ b/src/coders/commons.cpp @@ -57,3 +57,7 @@ std::string parsing_error::errorLog() const { ss << "^"; return ss.str(); } + +std::runtime_error parsing_error::toRuntimeError() const { + return std::runtime_error("parsing error: " + errorLog()); +} diff --git a/src/coders/commons.hpp b/src/coders/commons.hpp index d374cd92b..d1612cfd8 100644 --- a/src/coders/commons.hpp +++ b/src/coders/commons.hpp @@ -73,4 +73,6 @@ public: uint linestart ); std::string errorLog() const; + + std::runtime_error toRuntimeError() const; }; diff --git a/src/coders/xml.cpp b/src/coders/xml.cpp index b40ee7700..a907b49db 100644 --- a/src/coders/xml.cpp +++ b/src/coders/xml.cpp @@ -385,10 +385,22 @@ public: } if (c == '(') { nextChar(); - // TODO: replace with array parsing after moving to dv::value's - std::string value = std::string(readUntil(')')); + int depth = 1; + size_t start = pos; + while (hasNext()) { + char c = nextChar(); + if (c == '(') { + depth++; + } else if (c == ')') { + depth--; + if (depth == 0) { + goBack(1); + break; + } + } + } expect(')'); - return value; + return std::string(source.substr(start, pos - start - 1)); } return std::string(readUntilWhitespace()); } diff --git a/src/logic/scripting/lua/libs/libjson.cpp b/src/logic/scripting/lua/libs/libjson.cpp index a0caa4c33..a4354ea0c 100644 --- a/src/logic/scripting/lua/libs/libjson.cpp +++ b/src/logic/scripting/lua/libs/libjson.cpp @@ -1,4 +1,5 @@ #include "coders/json.hpp" +#include "coders/commons.hpp" #include "api_lua.hpp" static int l_json_stringify(lua::State* L) { @@ -12,8 +13,12 @@ static int l_json_stringify(lua::State* L) { static int l_json_parse(lua::State* L) { auto string = lua::require_string(L, 1); - auto element = json::parse("[string]", string); - return lua::pushvalue(L, element); + try { + auto element = json::parse("[string]", string); + return lua::pushvalue(L, element); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } } const luaL_Reg jsonlib[] = { diff --git a/src/logic/scripting/lua/libs/libtoml.cpp b/src/logic/scripting/lua/libs/libtoml.cpp index 4626ee3b9..947496d08 100644 --- a/src/logic/scripting/lua/libs/libtoml.cpp +++ b/src/logic/scripting/lua/libs/libtoml.cpp @@ -1,4 +1,5 @@ #include "coders/toml.hpp" +#include "coders/commons.hpp" #include "api_lua.hpp" using namespace scripting; @@ -16,8 +17,12 @@ static int l_toml_stringify(lua::State* L) { static int l_toml_parse(lua::State* L) { auto string = lua::require_string(L, 1); - auto element = toml::parse("[string]", string); - return lua::pushvalue(L, element); + try { + auto element = toml::parse("[string]", string); + return lua::pushvalue(L, element); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } } const luaL_Reg tomllib[] = { diff --git a/src/logic/scripting/lua/libs/libxml.cpp b/src/logic/scripting/lua/libs/libxml.cpp index 70ccc36bb..139e0ee35 100644 --- a/src/logic/scripting/lua/libs/libxml.cpp +++ b/src/logic/scripting/lua/libs/libxml.cpp @@ -1,8 +1,8 @@ #include "coders/xml.hpp" +#include "coders/commons.hpp" #include "api_lua.hpp" static const char* TAG_ATTR = "#"; -static const char* DEFAULT_ROOT_TAG = "root"; static int push_xml(lua::State* L, const xml::xmlelement& elem) { if (elem.isText()) { @@ -73,17 +73,26 @@ static int l_tostring(lua::State* L) { static int l_parse(lua::State* L) { auto string = lua::require_string(L, 1); - auto document = xml::parse("[string]", string); - return push_xml(L, *document->getRoot()); + try { + auto document = xml::parse("[string]", string); + return push_xml(L, *document->getRoot()); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } } - static int l_parse_vcd(lua::State* L) { auto string = lua::require_string(L, 1); auto rootTag = lua::tostring(L, 2); - auto document = xml::parse_vcm( - "[string]", string, rootTag ? rootTag : "" - ); + + std::unique_ptr document; + try { + document = xml::parse_vcm( + "[string]", string, rootTag ? rootTag : "" + ); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } const auto& root = *document->getRoot(); if (rootTag != nullptr) { return push_xml(L, root); diff --git a/src/logic/scripting/lua/libs/libyaml.cpp b/src/logic/scripting/lua/libs/libyaml.cpp index 42c9906c4..f951727af 100644 --- a/src/logic/scripting/lua/libs/libyaml.cpp +++ b/src/logic/scripting/lua/libs/libyaml.cpp @@ -1,4 +1,5 @@ #include "coders/yaml.hpp" +#include "coders/commons.hpp" #include "api_lua.hpp" static int l_stringify(lua::State* L) { @@ -9,8 +10,12 @@ static int l_stringify(lua::State* L) { static int l_parse(lua::State* L) { auto string = lua::require_string(L, 1); - auto element = yaml::parse("[string]", string); - return lua::pushvalue(L, element); + try { + auto element = yaml::parse("[string]", string); + return lua::pushvalue(L, element); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } } const luaL_Reg yamllib[] = { From e0bf82a71e15731aa0a4a6e8670bcf0c9cf392b7 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 23 Jul 2026 20:08:42 +0300 Subject: [PATCH 2/2] add filename info to content unit loading --- src/content/ContentLoader.cpp | 11 ++++++++++- src/io/io.cpp | 15 ++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 5120f5c59..14da690a2 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -178,7 +178,16 @@ void ContentUnitLoader::loadUnit( ) { auto folder = pack.folder; auto configFile = folder / (defsDir + "/" + name + ".json"); - if (io::exists(configFile)) loadUnit(def, full, configFile); + if (io::exists(configFile)) { + try { + loadUnit(def, full, configFile); + } catch (const std::runtime_error& err) { + throw std::runtime_error( + "file " + util::quote(configFile.string()) + ": " + + std::string(err.what()) + ); + } + } } void ContentLoader::loadBlockMaterial( diff --git a/src/io/io.cpp b/src/io/io.cpp index 2f4eab11c..638108587 100644 --- a/src/io/io.cpp +++ b/src/io/io.cpp @@ -173,8 +173,12 @@ bool io::write_binary_json( } dv::value io::read_json(const path& filename) { - std::string text = io::read_string(filename); - return json::parse(filename.string(), text); + auto text = io::read_string(filename); + try { + return json::parse(filename.string(), text); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } } dv::value io::read_binary_json(const path& file) { @@ -184,7 +188,12 @@ dv::value io::read_binary_json(const path& file) { } dv::value io::read_toml(const path& file) { - return toml::parse(file.string(), io::read_string(file)); + auto text = io::read_string(file); + try { + return toml::parse(file.string(), text); + } catch (const parsing_error& err) { + throw err.toRuntimeError(); + } } std::vector io::read_list(const io::path& filename) {