feat: toml lvalues support

This commit is contained in:
MihailRis 2024-10-12 00:23:52 +03:00
parent 66825d62aa
commit d14548cff8
7 changed files with 83 additions and 58 deletions

View File

@ -221,10 +221,6 @@ std::string_view BasicParser::readUntilEOL() {
std::string BasicParser::parseName() {
char c = peek();
if (!is_identifier_start(c)) {
if (c == '"') {
pos++;
return parseString(c);
}
throw error("identifier expected");
}
int start = pos;
@ -234,6 +230,18 @@ std::string BasicParser::parseName() {
return std::string(source.substr(start, pos - start));
}
std::string BasicParser::parseXmlName() {
char c = peek();
if (!is_json_identifier_start(c)) {
throw error("identifier expected");
}
int start = pos;
while (hasNext() && is_json_identifier_part(source[pos])) {
pos++;
}
return std::string(source.substr(start, pos - start));
}
int64_t BasicParser::parseSimpleInt(int base) {
char c = peek();
int index = hexchar2int(c);

View File

@ -30,14 +30,22 @@ inline bool is_whitespace(int c) {
}
inline bool is_identifier_start(int c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' ||
c == '.';
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_';
}
inline bool is_identifier_part(int c) {
return is_identifier_start(c) || is_digit(c) || c == '-';
}
inline bool is_json_identifier_start(int c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' ||
c == '.';
}
inline bool is_json_identifier_part(int c) {
return is_json_identifier_start(c) || is_digit(c) || c == '-';
}
inline int hexchar2int(int c) {
if (c >= '0' && c <= '9') {
return c - '0';
@ -99,6 +107,7 @@ public:
std::string_view readUntil(char c);
std::string_view readUntilEOL();
std::string parseName();
std::string parseXmlName();
bool hasNext();
char peek();
char peekInLine();

View File

@ -178,7 +178,8 @@ dv::value Parser::parseObject() {
skipLine();
continue;
}
std::string key = parseName();
expect('"');
std::string key = parseString('"');
char next = peek();
if (next != ':') {
throw error("':' expected");

View File

@ -26,32 +26,6 @@ class TomlReader : BasicParser {
}
}
dv::value& getSection(const std::string& section) {
if (section.empty()) {
return root;
}
size_t offset = 0;
auto rootMap = &root;
do {
size_t index = section.find('.', offset);
if (index == std::string::npos) {
auto map = rootMap->at(section);
if (!map) {
return rootMap->object(section);
}
return *map;
}
auto subsection = section.substr(offset, index);
auto map = rootMap->at(subsection);
if (!map) {
rootMap = &rootMap->object(subsection);
} else {
rootMap = &*map;
}
offset = index + 1;
} while (true);
}
dv::value parseValue() {
char c = peek();
if (is_digit(c)) {
@ -111,7 +85,30 @@ class TomlReader : BasicParser {
}
}
void readSection(const std::string& section, dv::value& map) {
dv::value& parseLValue(dv::value& root) {
dv::value* lvalue = &root;
while (hasNext()) {
char c = peek();
std::string name;
if (c == '\'' || c == '"') {
pos++;
name = parseString(c);
} else {
name = parseName();
}
if (lvalue->getType() == dv::value_type::none) {
*lvalue = dv::object();
}
lvalue = &(*lvalue)[name];
if (peek() != '.') {
break;
}
pos++;
}
return *lvalue;
}
void readSection(dv::value& map, dv::value& root) {
while (hasNext()) {
skipWhitespace();
if (!hasNext()) {
@ -119,15 +116,15 @@ class TomlReader : BasicParser {
}
char c = nextChar();
if (c == '[') {
std::string name = parseName();
pos++;
readSection(name, getSection(name));
dv::value& section = parseLValue(root);
expect(']');
readSection(section, root);
return;
}
pos--;
std::string name = parseName();
dv::value& lvalue = parseLValue(map);
expect('=');
map[name] = parseValue();
lvalue = parseValue();
expectNewLine();
}
}
@ -141,7 +138,7 @@ public:
if (!hasNext()) {
return std::move(root);
}
readSection("", root);
readSection(root, root);
return std::move(root);
}
};
@ -150,6 +147,7 @@ void toml::parse(
SettingsHandler& handler, std::string_view file, std::string_view source
) {
auto map = parse(file, source);
for (const auto& [sectionName, sectionMap] : map.asObject()) {
if (!sectionMap.isObject()) {
continue;

View File

@ -157,5 +157,5 @@ namespace dv {
#include "coders/json.hpp"
std::ostream& operator<<(std::ostream& stream, const dv::value& value) {
return stream << json::stringify(value, false);
return stream << json::stringify(value, true);
}

View File

@ -9,6 +9,7 @@
#include "coders/imageio.hpp"
#include "coders/json.hpp"
#include "coders/toml.hpp"
#include "coders/commons.hpp"
#include "content/Content.hpp"
#include "content/ContentBuilder.hpp"
#include "content/ContentLoader.hpp"
@ -125,7 +126,12 @@ void Engine::loadSettings() {
if (fs::is_regular_file(settings_file)) {
logger.info() << "loading settings";
std::string text = files::read_string(settings_file);
toml::parse(settingsHandler, settings_file.string(), text);
try {
toml::parse(settingsHandler, settings_file.string(), text);
} catch (const parsing_error& err) {
logger.error() << err.errorLog();
throw;
}
}
}

View File

@ -196,22 +196,25 @@ void Events::loadBindings(
const std::string& filename, const std::string& source
) {
auto map = toml::parse(filename, source);
for (auto& [key, value] : map.asObject()) {
auto [prefix, codename] = util::split_at(value.asString(), ':');
inputtype type;
int code;
if (prefix == "key") {
type = inputtype::keyboard;
code = static_cast<int>(input_util::keycode_from(codename));
} else if (prefix == "mouse") {
type = inputtype::mouse;
code = static_cast<int>(input_util::mousecode_from(codename));
} else {
logger.error()
<< "unknown input type: " << prefix << " (binding "
<< util::quote(key) << ")";
continue;
for (auto& [sectionName, section] : map.asObject()) {
for (auto& [name, value] : section.asObject()) {
auto key = sectionName + "." + name;
auto [prefix, codename] = util::split_at(value.asString(), ':');
inputtype type;
int code;
if (prefix == "key") {
type = inputtype::keyboard;
code = static_cast<int>(input_util::keycode_from(codename));
} else if (prefix == "mouse") {
type = inputtype::mouse;
code = static_cast<int>(input_util::mousecode_from(codename));
} else {
logger.error()
<< "unknown input type: " << prefix << " (binding "
<< util::quote(key) << ")";
continue;
}
Events::bind(key, type, code);
}
Events::bind(key, type, code);
}
}