From e2e180b9a5b38df0ef52a4a8df9e84051d50f0e0 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 14 Oct 2022 20:27:45 +0300 Subject: [PATCH] chore --- include/compiler/treeifier/ast.hh | 49 ++++++------ include/compiler/treeifier/ast/helper.hh | 17 ++-- include/utils/data.hh | 24 +++--- include/utils/message.hh | 6 ++ src/compiler/treeifier/ast.cc | 13 ++- src/compiler/treeifier/ast/conv.cc | 2 +- src/compiler/treeifier/ast/parsers/field.cc | 44 ++++++++++ src/compiler/treeifier/ast/parsers/glob.cc | 20 ++++- src/compiler/treeifier/ast/parsers/group.cc | 25 +++--- .../treeifier/ast/parsers/identifier.cc | 2 +- src/compiler/treeifier/ast/parsers/nmsp.cc | 2 +- src/compiler/treeifier/ast/parsers/type.cc | 2 +- src/utils/data.cc | 80 ++++++++++--------- 13 files changed, 186 insertions(+), 100 deletions(-) create mode 100644 src/compiler/treeifier/ast/parsers/field.cc diff --git a/include/compiler/treeifier/ast.hh b/include/compiler/treeifier/ast.hh index e4c80ef..68d0aea 100644 --- a/include/compiler/treeifier/ast.hh +++ b/include/compiler/treeifier/ast.hh @@ -16,15 +16,16 @@ using namespace ppc::messages; namespace ppc::comp::tree::ast { class parser_t; class group_parser_t; + struct ast_ctx_t; - using parser_factory_t = parser_t *(*)(); - using group_parser_factory_t = group_parser_t *(*)(); + using parser_adder_t = void (*)(ast_ctx_t &ctx); - extern parser_factory_t glob_parser; - extern parser_factory_t identifier_parser; - extern parser_factory_t nmsp_parser; - extern parser_factory_t type_parser; - extern group_parser_factory_t def_parser; + extern const parser_adder_t glob_adder; + extern const parser_adder_t identifier_adder; + extern const parser_adder_t nmsp_adder; + extern const parser_adder_t type_adder; + extern const parser_adder_t exp_adder; + extern const parser_adder_t field_adder; struct ast_ctx_t { private: @@ -40,23 +41,23 @@ namespace ppc::comp::tree::ast { private: ast_ctx_t *parent; public: - const group_parser_t &operator[](const std::string &name) const; + group_parser_t &operator[](const std::string &name) const; group_proxy_t(ast_ctx_t *parent): parent(parent) { } }; std::unordered_map parsers; - std::set groups; - - void add_parser(const parser_t *parser); - void add_parser(const group_parser_t *parser); + std::set groups; public: msg_stack_t &messages; std::vector &tokens; std::set imports; loc_namespace_name_t nmsp; - void add_parser(parser_factory_t factory) { add_parser(factory()); } - void add_parser(group_parser_factory_t factory) { add_parser(factory()); } + void add_parser(const parser_t *parser); + void add_parser(const parser_t *parser, const std::string &group); + void add_group(const std::string &name); + + void add_parser(parser_adder_t factory) { factory(*this); } ast_ctx_t &operator=(const ast_ctx_t &other) = delete; @@ -64,11 +65,13 @@ namespace ppc::comp::tree::ast { const group_proxy_t group; ast_ctx_t &init() { - add_parser(glob_parser); - add_parser(identifier_parser); - add_parser(nmsp_parser); - add_parser(def_parser); - add_parser(type_parser); + add_parser(identifier_adder); + add_parser(nmsp_adder); + add_parser(glob_adder); + add_parser(type_adder); + add_parser(exp_adder); + add_parser(field_adder); + return *this; } @@ -102,11 +105,11 @@ namespace ppc::comp::tree::ast { class group_parser_t : public parser_t { private: - std::vector> named_parsers; - std::vector parsers; + std::vector> named_parsers; + std::vector parsers; public: - group_parser_t &add(parser_t &parser); - group_parser_t &add(parser_t &parser, const lang::namespace_name_t &name); + group_parser_t &add(const parser_t &parser); + group_parser_t &add(const parser_t &parser, const lang::namespace_name_t &name); bool parse(ast_ctx_t &ctx, size_t &i, data::map_t &out) const; diff --git a/include/compiler/treeifier/ast/helper.hh b/include/compiler/treeifier/ast/helper.hh index 7eb965b..a9a418d 100644 --- a/include/compiler/treeifier/ast/helper.hh +++ b/include/compiler/treeifier/ast/helper.hh @@ -12,14 +12,15 @@ namespace ppc::comp::tree::ast { ast_ctx_t &ctx; size_t &res_i; + public: + size_t i; + void throw_ended() { if (ended()) throw messages::message_t(message_t::ERROR, "Unexpected end.", loc()); } void throw_ended(const std::string &reason) { if (ended()) throw messages::message_t(message_t::ERROR, "Unexpected end: " + reason, loc()); } - public: - size_t i; location_t loc(size_t n) { location_t res = prev_loc(); @@ -62,10 +63,10 @@ namespace ppc::comp::tree::ast { else return ctx.tokens[res_i].location.intersect(loc()); } - void err(std::string message) { + bool err(std::string message) { throw message_t::error(message, loc()); } - void err(std::string message, size_t n) { + bool err(std::string message, size_t n) { throw message_t::error(message, loc(n)); } @@ -78,6 +79,10 @@ namespace ppc::comp::tree::ast { return i == ctx.tokens.size(); } + token_t &curr(const std::string &reason) { + throw_ended(reason); + return ctx.tokens[i]; + } token_t &curr() { throw_ended(); return ctx.tokens[i]; @@ -113,7 +118,7 @@ namespace ppc::comp::tree::ast { } void force_push_parse(const std::string &name, std::string message, data::array_t &out) { - advance(message); + throw_ended(message); bool success; try { @@ -127,7 +132,7 @@ namespace ppc::comp::tree::ast { if (!success) err(message); } void force_parse(const std::string &name, std::string message, data::map_t &out) { - advance(message); + throw_ended(message); bool success; try { diff --git a/include/utils/data.hh b/include/utils/data.hh index c4a903b..a5ed6d2 100644 --- a/include/utils/data.hh +++ b/include/utils/data.hh @@ -39,16 +39,22 @@ namespace ppc::data { bool is_string() const; bool is_bool() const; - bool array(array_t &out) const; - bool map(map_t &out) const; - bool number(number_t &out) const; - bool string(string_t &out) const; - bool boolean(bool_t &out) const; + array_t &array(const array_t &arr); + map_t &map(const map_t &map); + number_t &number(number_t num); + string_t &string(const string_t &str); + bool_t &boolean(bool_t bl); - array_t &array() const; - map_t &map() const; + array_t &array(); + map_t &map(); + number_t &number(); + string_t &string(); + bool_t &boolean(); + + const array_t &array() const; + const map_t &map() const; number_t number() const; - string_t &string() const; + const string_t &string() const; bool_t boolean() const; value_t &operator=(const value_t &other); @@ -65,8 +71,6 @@ namespace ppc::data { value_t(bool_t val); value_t(const value_t &other); - static value_t mk_arr(); - static value_t mk_map(); }; diff --git a/include/utils/message.hh b/include/utils/message.hh index 63a73b8..75886d8 100644 --- a/include/utils/message.hh +++ b/include/utils/message.hh @@ -38,7 +38,13 @@ namespace ppc::messages { inline auto begin() { return messages.begin(); } inline auto end() { return messages.end(); } + inline auto begin() const { return messages.begin(); } + inline auto end() const { return messages.end(); } + void push(const message_t &msg) { messages.push_back(msg); } + void push(const msg_stack_t &other) { + for (const auto &msg : other) push(msg); + } const message_t &peek() { return messages.back(); } void clear() { messages.clear(); } diff --git a/src/compiler/treeifier/ast.cc b/src/compiler/treeifier/ast.cc index b93e5e4..aca1368 100644 --- a/src/compiler/treeifier/ast.cc +++ b/src/compiler/treeifier/ast.cc @@ -8,10 +8,10 @@ namespace ppc::comp::tree::ast { if (it == parent->parsers.end()) throw "The parser '" + name + "' doesn't exist."; return *it->second; } - const group_parser_t &ast_ctx_t::group_proxy_t::operator[](const std::string &name) const { - auto p = &parent->parser[name]; + group_parser_t &ast_ctx_t::group_proxy_t::operator[](const std::string &name) const { + auto p = (group_parser_t*)&parent->parser[name]; if (parent->groups.find(p) == parent->groups.end()) throw "A parser '" + name + "' exists, but isn't a group."; - return *(const group_parser_t*)p; + return *p; } ast_ctx_t::~ast_ctx_t() { @@ -24,7 +24,12 @@ namespace ppc::comp::tree::ast { if (parsers.find(parser->name()) != parsers.end()) throw "The parser '" + parser->name() + "' already exists."; parsers[parser->name()] = parser; } - void ast_ctx_t::add_parser(const group_parser_t *parser) { + void ast_ctx_t::add_parser(const parser_t *parser, const std::string &group) { + add_parser(parser); + this->group[group].add(*parser); + } + void ast_ctx_t::add_group(const std::string &name) { + auto parser = new group_parser_t(name); if (parsers.find(parser->name()) != parsers.end()) throw "The parser '" + parser->name() + "' already exists."; parsers[parser->name()] = parser; groups.emplace(parser); diff --git a/src/compiler/treeifier/ast/conv.cc b/src/compiler/treeifier/ast/conv.cc index 2526922..2bf6c73 100644 --- a/src/compiler/treeifier/ast/conv.cc +++ b/src/compiler/treeifier/ast/conv.cc @@ -51,7 +51,7 @@ namespace ppc::comp::tree::ast::conv { data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp) { data::map_t res; - auto arr = (res["content"] = data::array_t()).array(); + auto arr = res["content"].array({}); for (const auto &segment : nmsp) { arr.push({ diff --git a/src/compiler/treeifier/ast/parsers/field.cc b/src/compiler/treeifier/ast/parsers/field.cc new file mode 100644 index 0000000..79d1c0f --- /dev/null +++ b/src/compiler/treeifier/ast/parsers/field.cc @@ -0,0 +1,44 @@ +#include "compiler/treeifier/ast/helper.hh" + +class field_parser_t : public parser_t { + bool parse(ast_ctx_t &ctx, size_t &res_i, map_t &out) const { + tree_helper_t h(ctx, res_i); + + if (h.ended()) return false; + + if (!h.parse("$_identifier", out["name"].map({}))) return false; + + bool type, defval; + + h.throw_ended("Expected a colon or an equals sign."); + + if (h.curr().is_operator(operator_t::COLON)) { + h.advance(); + h.force_parse("$_type", "Expected a type.", out["type"].map({})); + type = true; + } + if (h.curr().is_operator(operator_t::ASSIGN)) { + h.i++; + h.err("Default values are not yet supported.", 1); + h.advance(); + h.force_parse("$_exp", "Expected an expression.", out["value"].map({})); + type = true; + } + + if (h.curr().is_operator(operator_t::SEMICOLON)) { + if (type || defval) return h.submit(); + else return h.err("A type or a default value must be specified "); + } + else if (type || defval) { + ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1))); + return h.submit(false); + } + else return false; + + return h.submit(true); + } + + public: field_parser_t(): parser_t("$_field") { } +}; + +parser_adder_t ppc::comp::tree::ast::field_adder = [](ast_ctx_t &ctx) { ctx.add_parser(new field_parser_t(), "$_def"); }; diff --git a/src/compiler/treeifier/ast/parsers/glob.cc b/src/compiler/treeifier/ast/parsers/glob.cc index 54dcde7..427b718 100644 --- a/src/compiler/treeifier/ast/parsers/glob.cc +++ b/src/compiler/treeifier/ast/parsers/glob.cc @@ -9,6 +9,7 @@ class nmsp_def_parser_t : public parser_t { if (h.ended()) return false; if (!h.curr().is_identifier("namespace")) return false; + h.advance("Expected a namespace"); h.force_parse("$_nmsp", "Expected a namespace.", res); if (!h.curr().is_operator(operator_t::SEMICOLON)) { ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1))); @@ -25,6 +26,7 @@ class import_parser_t : public parser_t { if (h.ended()) return false; if (!h.curr().is_identifier("import")) return false; + h.advance("Expected a namespace"); h.force_parse("$_nmsp", "Expected a namespace.", res); if (!h.curr().is_operator(operator_t::SEMICOLON)) { ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1))); @@ -49,7 +51,7 @@ class glob_parser_t : public parser_t { } auto &imports = (out["imports"] = array_t()).array(); - /* auto &contents = */ (out["content"] = array_t()).array(); + auto &contents = (out["content"] = array_t()).array(); while (true) { map_t map; @@ -60,9 +62,16 @@ class glob_parser_t : public parser_t { if (!ctx.imports.emplace(nmsp).second) h.err("The namespace '" + nmsp.to_string() + "' is already imported."); } + while (true) { + if (h.ended()) break; + if (!h.push_parse("$_def", contents)) { + ctx.messages.push(message_t::error("Invalid token.", h.loc())); + h.i++; + } + } + if (!h.ended()) h.err("Invalid token."); - if (ctx.messages.is_failed()) return false; return h.submit(); } @@ -70,5 +79,8 @@ public: glob_parser_t(): parser_t("$_glob") { } }; -parser_factory_t ppc::comp::tree::ast::glob_parser = []() { return (parser_t*)new glob_parser_t(); }; -group_parser_factory_t ppc::comp::tree::ast::def_parser = []() { return new group_parser_t("$_def"); }; +parser_adder_t ppc::comp::tree::ast::glob_adder = [](ast_ctx_t &ctx) { + ctx.add_parser(new group_parser_t("$_def")); + ctx.add_parser(new group_parser_t("$_expr_val")); + ctx.add_parser(new glob_parser_t()); +}; diff --git a/src/compiler/treeifier/ast/parsers/group.cc b/src/compiler/treeifier/ast/parsers/group.cc index 01934f2..7e19636 100644 --- a/src/compiler/treeifier/ast/parsers/group.cc +++ b/src/compiler/treeifier/ast/parsers/group.cc @@ -2,10 +2,13 @@ #include "compiler/treeifier/tokenizer.hh" #include "compiler/treeifier/ast/helper.hh" #include +#include +#include using namespace ppc::comp::tree; using namespace ppc::comp::tree::ast; using namespace std::string_literals; +using namespace std; static bool read_nmsp(ast_ctx_t &ctx, size_t &i, const lang::namespace_name_t &name) { tree_helper_t h(ctx, i); @@ -33,29 +36,31 @@ static bool read_nmsp(ast_ctx_t &ctx, size_t &i, const lang::namespace_name_t &n bool group_parser_t::parse(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { tree_helper_t h(ctx, i); + if (h.ended()) return false; + for (auto &pair : named_parsers) { if (!read_nmsp(ctx, i, pair.first)) continue; auto &parser = *pair.second; - return parser(ctx, i, out); + if (parser(ctx, i, out)) return true; + else throw message_t::error("Unexpected construct specifier.", h.res_loc()); } + + unordered_map errors; + for (auto parser : parsers) { - try { - return (*parser)(ctx, i, out); - } - catch (const message_t &err) { - ctx.messages.push(err); - return false; - } + if ((*parser)(ctx, i, out)) return true; } + stringstream m; + return false; } -group_parser_t &group_parser_t::add(parser_t &parser) { +group_parser_t &group_parser_t::add(const parser_t &parser) { parsers.push_back(&parser); return *this; } -group_parser_t &group_parser_t::add(parser_t &parser, const lang::namespace_name_t &name) { +group_parser_t &group_parser_t::add(const parser_t &parser, const lang::namespace_name_t &name) { if (name.empty()) throw "Name can't be empty."s; if (std::find(parsers.begin(), parsers.end(), &parser) != parsers.end()) { throw "Parser '" + name.to_string() + "' already in group."; diff --git a/src/compiler/treeifier/ast/parsers/identifier.cc b/src/compiler/treeifier/ast/parsers/identifier.cc index 59af7e0..3b3d2fc 100644 --- a/src/compiler/treeifier/ast/parsers/identifier.cc +++ b/src/compiler/treeifier/ast/parsers/identifier.cc @@ -18,4 +18,4 @@ class identifier_parser_t : public parser_t { public: identifier_parser_t(): parser_t("$_identifier") { } }; -parser_factory_t ppc::comp::tree::ast::identifier_parser = []() { return (parser_t*)new identifier_parser_t(); }; +parser_adder_t ppc::comp::tree::ast::identifier_adder = [](ast_ctx_t &ctx) { ctx.add_parser(new identifier_parser_t()); }; diff --git a/src/compiler/treeifier/ast/parsers/nmsp.cc b/src/compiler/treeifier/ast/parsers/nmsp.cc index 0ae7bca..b1bd4b4 100644 --- a/src/compiler/treeifier/ast/parsers/nmsp.cc +++ b/src/compiler/treeifier/ast/parsers/nmsp.cc @@ -23,4 +23,4 @@ class nmsp_parser_t : public parser_t { public: nmsp_parser_t(): parser_t("$_nmsp") { } }; -parser_factory_t ppc::comp::tree::ast::nmsp_parser = []() { return (parser_t*)new nmsp_parser_t(); }; +parser_adder_t ppc::comp::tree::ast::nmsp_adder = [](ast_ctx_t &ctx) { ctx.add_parser(new nmsp_parser_t()); }; diff --git a/src/compiler/treeifier/ast/parsers/type.cc b/src/compiler/treeifier/ast/parsers/type.cc index 43fd921..0425a4d 100644 --- a/src/compiler/treeifier/ast/parsers/type.cc +++ b/src/compiler/treeifier/ast/parsers/type.cc @@ -47,4 +47,4 @@ class type_parser_t : public parser_t { public: type_parser_t(): parser_t("$_type") { } }; -parser_factory_t ppc::comp::tree::ast::type_parser = []() { return (parser_t*)new type_parser_t(); }; +parser_adder_t ppc::comp::tree::ast::type_adder = [](ast_ctx_t &ctx) { ctx.add_parser(new type_parser_t()); }; diff --git a/src/utils/data.cc b/src/utils/data.cc index f8ac7ce..f83e097 100644 --- a/src/utils/data.cc +++ b/src/utils/data.cc @@ -20,47 +20,55 @@ namespace ppc::data { return type == type_t::Bool; } - bool value_t::array(array_t &out) const { - if (is_array()) { - out = *val.arr; - return true; - } - return false; + array_t &value_t::array(const array_t &val) { + *this = val; + return *this->val.arr; } - bool value_t::map(map_t &out) const { - if (is_map()) { - out = *val.map; - return true; - } - return false; + map_t &value_t::map(const map_t &val) { + *this = val; + return *this->val.map; } - bool value_t::number(number_t &out) const { - if (is_number()) { - out = val.num; - return true; - } - return false; + number_t &value_t::number(number_t val) { + *this = val; + return this->val.num; } - bool value_t::string(string_t &out) const { - if (is_string()) { - out = *val.str; - return true; - } - return false; + string_t &value_t::string(const string_t &val) { + *this = val; + return *this->val.str; } - bool value_t::boolean(bool_t &out) const { - if (is_bool()) { - out = val.bl; - return true; - } - return false; + bool_t &value_t::boolean(bool_t val) { + *this = val; + return this->val.bl; } - array_t &value_t::array() const { + + array_t &value_t::array() { if (is_array()) return *val.arr; else throw (std::string)"The value isn't an array."; } - map_t &value_t::map() const { + map_t &value_t::map() { + if (is_map()) return *val.map; + else throw (std::string)"The value isn't a map."; + } + number_t &value_t::number() { + if (is_number()) return val.num; + else throw (std::string)"The value isn't a number."; + } + string_t &value_t::string() { + if (is_string()) return *val.str; + else throw (std::string)"The value isn't a string."; + } + bool_t &value_t::boolean() { + if (is_bool()) return val.bl; + else throw (std::string)"The value isn't a bool."; + } + + + const array_t &value_t::array() const { + if (is_array()) return *val.arr; + else throw (std::string)"The value isn't an array."; + } + const map_t &value_t::map() const { if (is_map()) return *val.map; else throw (std::string)"The value isn't a map."; } @@ -68,7 +76,7 @@ namespace ppc::data { if (is_number()) return val.num; else throw (std::string)"The value isn't a number."; } - string_t &value_t::string() const { + const string_t &value_t::string() const { if (is_string()) return *val.str; else throw (std::string)"The value isn't a string."; } @@ -121,12 +129,6 @@ namespace ppc::data { break; } } - value_t value_t::mk_arr() { - return value_t(array_t()); - } - value_t value_t::mk_map() { - return value_t(map_t()); - } value_t::~value_t() { switch (type) {