feat: toml lvalues support
This commit is contained in:
parent
66825d62aa
commit
d14548cff8
@ -221,10 +221,6 @@ std::string_view BasicParser::readUntilEOL() {
|
|||||||
std::string BasicParser::parseName() {
|
std::string BasicParser::parseName() {
|
||||||
char c = peek();
|
char c = peek();
|
||||||
if (!is_identifier_start(c)) {
|
if (!is_identifier_start(c)) {
|
||||||
if (c == '"') {
|
|
||||||
pos++;
|
|
||||||
return parseString(c);
|
|
||||||
}
|
|
||||||
throw error("identifier expected");
|
throw error("identifier expected");
|
||||||
}
|
}
|
||||||
int start = pos;
|
int start = pos;
|
||||||
@ -234,6 +230,18 @@ std::string BasicParser::parseName() {
|
|||||||
return std::string(source.substr(start, pos - start));
|
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) {
|
int64_t BasicParser::parseSimpleInt(int base) {
|
||||||
char c = peek();
|
char c = peek();
|
||||||
int index = hexchar2int(c);
|
int index = hexchar2int(c);
|
||||||
|
|||||||
@ -30,14 +30,22 @@ inline bool is_whitespace(int c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_identifier_start(int c) {
|
inline bool is_identifier_start(int c) {
|
||||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' ||
|
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_';
|
||||||
c == '.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_identifier_part(int c) {
|
inline bool is_identifier_part(int c) {
|
||||||
return is_identifier_start(c) || is_digit(c) || 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) {
|
inline int hexchar2int(int c) {
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
return c - '0';
|
return c - '0';
|
||||||
@ -99,6 +107,7 @@ public:
|
|||||||
std::string_view readUntil(char c);
|
std::string_view readUntil(char c);
|
||||||
std::string_view readUntilEOL();
|
std::string_view readUntilEOL();
|
||||||
std::string parseName();
|
std::string parseName();
|
||||||
|
std::string parseXmlName();
|
||||||
bool hasNext();
|
bool hasNext();
|
||||||
char peek();
|
char peek();
|
||||||
char peekInLine();
|
char peekInLine();
|
||||||
|
|||||||
@ -178,7 +178,8 @@ dv::value Parser::parseObject() {
|
|||||||
skipLine();
|
skipLine();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string key = parseName();
|
expect('"');
|
||||||
|
std::string key = parseString('"');
|
||||||
char next = peek();
|
char next = peek();
|
||||||
if (next != ':') {
|
if (next != ':') {
|
||||||
throw error("':' expected");
|
throw error("':' expected");
|
||||||
|
|||||||
@ -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() {
|
dv::value parseValue() {
|
||||||
char c = peek();
|
char c = peek();
|
||||||
if (is_digit(c)) {
|
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()) {
|
while (hasNext()) {
|
||||||
skipWhitespace();
|
skipWhitespace();
|
||||||
if (!hasNext()) {
|
if (!hasNext()) {
|
||||||
@ -119,15 +116,15 @@ class TomlReader : BasicParser {
|
|||||||
}
|
}
|
||||||
char c = nextChar();
|
char c = nextChar();
|
||||||
if (c == '[') {
|
if (c == '[') {
|
||||||
std::string name = parseName();
|
dv::value& section = parseLValue(root);
|
||||||
pos++;
|
expect(']');
|
||||||
readSection(name, getSection(name));
|
readSection(section, root);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pos--;
|
pos--;
|
||||||
std::string name = parseName();
|
dv::value& lvalue = parseLValue(map);
|
||||||
expect('=');
|
expect('=');
|
||||||
map[name] = parseValue();
|
lvalue = parseValue();
|
||||||
expectNewLine();
|
expectNewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +138,7 @@ public:
|
|||||||
if (!hasNext()) {
|
if (!hasNext()) {
|
||||||
return std::move(root);
|
return std::move(root);
|
||||||
}
|
}
|
||||||
readSection("", root);
|
readSection(root, root);
|
||||||
return std::move(root);
|
return std::move(root);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -150,6 +147,7 @@ void toml::parse(
|
|||||||
SettingsHandler& handler, std::string_view file, std::string_view source
|
SettingsHandler& handler, std::string_view file, std::string_view source
|
||||||
) {
|
) {
|
||||||
auto map = parse(file, source);
|
auto map = parse(file, source);
|
||||||
|
|
||||||
for (const auto& [sectionName, sectionMap] : map.asObject()) {
|
for (const auto& [sectionName, sectionMap] : map.asObject()) {
|
||||||
if (!sectionMap.isObject()) {
|
if (!sectionMap.isObject()) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -157,5 +157,5 @@ namespace dv {
|
|||||||
#include "coders/json.hpp"
|
#include "coders/json.hpp"
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const dv::value& value) {
|
std::ostream& operator<<(std::ostream& stream, const dv::value& value) {
|
||||||
return stream << json::stringify(value, false);
|
return stream << json::stringify(value, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "coders/imageio.hpp"
|
#include "coders/imageio.hpp"
|
||||||
#include "coders/json.hpp"
|
#include "coders/json.hpp"
|
||||||
#include "coders/toml.hpp"
|
#include "coders/toml.hpp"
|
||||||
|
#include "coders/commons.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "content/ContentBuilder.hpp"
|
#include "content/ContentBuilder.hpp"
|
||||||
#include "content/ContentLoader.hpp"
|
#include "content/ContentLoader.hpp"
|
||||||
@ -125,7 +126,12 @@ void Engine::loadSettings() {
|
|||||||
if (fs::is_regular_file(settings_file)) {
|
if (fs::is_regular_file(settings_file)) {
|
||||||
logger.info() << "loading settings";
|
logger.info() << "loading settings";
|
||||||
std::string text = files::read_string(settings_file);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -196,22 +196,25 @@ void Events::loadBindings(
|
|||||||
const std::string& filename, const std::string& source
|
const std::string& filename, const std::string& source
|
||||||
) {
|
) {
|
||||||
auto map = toml::parse(filename, source);
|
auto map = toml::parse(filename, source);
|
||||||
for (auto& [key, value] : map.asObject()) {
|
for (auto& [sectionName, section] : map.asObject()) {
|
||||||
auto [prefix, codename] = util::split_at(value.asString(), ':');
|
for (auto& [name, value] : section.asObject()) {
|
||||||
inputtype type;
|
auto key = sectionName + "." + name;
|
||||||
int code;
|
auto [prefix, codename] = util::split_at(value.asString(), ':');
|
||||||
if (prefix == "key") {
|
inputtype type;
|
||||||
type = inputtype::keyboard;
|
int code;
|
||||||
code = static_cast<int>(input_util::keycode_from(codename));
|
if (prefix == "key") {
|
||||||
} else if (prefix == "mouse") {
|
type = inputtype::keyboard;
|
||||||
type = inputtype::mouse;
|
code = static_cast<int>(input_util::keycode_from(codename));
|
||||||
code = static_cast<int>(input_util::mousecode_from(codename));
|
} else if (prefix == "mouse") {
|
||||||
} else {
|
type = inputtype::mouse;
|
||||||
logger.error()
|
code = static_cast<int>(input_util::mousecode_from(codename));
|
||||||
<< "unknown input type: " << prefix << " (binding "
|
} else {
|
||||||
<< util::quote(key) << ")";
|
logger.error()
|
||||||
continue;
|
<< "unknown input type: " << prefix << " (binding "
|
||||||
|
<< util::quote(key) << ")";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Events::bind(key, type, code);
|
||||||
}
|
}
|
||||||
Events::bind(key, type, code);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user