From 4d622c9570100b43f85ab5dd8885444b6e47eca1 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 24 Nov 2022 16:03:16 +0200 Subject: [PATCH 1/4] chore: remove old lang syste, --- include/lang/namespace.hh | 38 -------------------------- include/lang/operator.hh | 57 --------------------------------------- include/lang/types.hh | 51 ----------------------------------- 3 files changed, 146 deletions(-) delete mode 100644 include/lang/namespace.hh delete mode 100644 include/lang/operator.hh delete mode 100644 include/lang/types.hh diff --git a/include/lang/namespace.hh b/include/lang/namespace.hh deleted file mode 100644 index 5e293a6..0000000 --- a/include/lang/namespace.hh +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "lang/common.hh" -#include "lang/types.hh" -#include "lang/version.hh" - -namespace ppc::lang { - // A structure, containing all the definitions of a namespace - struct namespace_t { - // The name of the namespace - namespace_name_t name; - // The version of the namespace - version_t version; - // A list of all the defined types inside the namespace - std::vector types; - // A list of all the defined fields inside the namespace - std::vector fields; - - bool contains_def(const std::string &name, location_t &ploc) const; - inline bool contains_def(const std::string &name) const { - location_t ploc; - return contains_def(name, ploc); - } - - template - static bool contains_def(T namespaces, const namespace_name_t &def_nmsp, const std::string &name, location_t &ploc) { - for (const namespace_t &nmsp : namespaces) { - if (nmsp.name == def_nmsp && nmsp.contains_def(name)) return true; - } - return false; - } - template - static inline bool contains_def(T namespaces, const namespace_name_t &def_nmsp, const std::string &name) { - location_t ploc; - return contains_def(namespaces, def_nmsp, name, ploc); - } - }; -} diff --git a/include/lang/operator.hh b/include/lang/operator.hh deleted file mode 100644 index bd09dbf..0000000 --- a/include/lang/operator.hh +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include - -enum operator_t { - OPERATOR_NONE, - OPERATOR_LESS_THAN, - OPERATOR_GREATER_THAN, - OPERATOR_LESS_THAN_EQUALS, - OPERATOR_GREATER_THAN_EQUALS, - OPERATOR_EQUALS, - OPERATOR_NOT_EQUALS, - OPERATOR_BOOLEAN_AND, - OPERATOR_BOOLEAN_OR, - - OPERATOR_SHIFT_LEFT, - OPERATOR_SHIFT_RIGHT, - OPERATOR_BINARY_XOR, - OPERATOR_BINARY_AND, - OPERATOR_BINARY_OR, - OPERATOR_BOOLEAN_NOT, - OPERATOR_BITWISE_NEGATIVE, - - OPERATOR_INCREASE, - OPERATOR_DECREASE, - - OPERATOR_POST_INCREASE, - OPERATOR_POST_DECREASE, - - OPERATOR_ADD, - OPERATOR_SUBTRACT, - OPERATOR_DIVIDE, - OPERATOR_MULTIPLY, - OPERATOR_MODULO, - - OPERATOR_POSITIVE, - OPERATOR_NEGATIVE, - - OPERATOR_CONDITIONAL, - OPERATOR_NULL_COALESCING, - - OPERATOR_IMPLICIT, - OPERATOR_EXPLICIT, - - OPERATOR_NEW, - OPERATOR_VAL, - - OPERATOR_ASSIGN, - - OPERATOR_PTR_MEMBER, - OPERATOR_MEMBER, - - OPERATOR_REFERENCING, - OPERATOR_DEREFERENCING, - - OPERATOR_CALL, -}; diff --git a/include/lang/types.hh b/include/lang/types.hh deleted file mode 100644 index 53a0750..0000000 --- a/include/lang/types.hh +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "utils/location.hh" -#include "lang/common.hh" -#include "lang/version.hh" - -namespace ppc::lang { - enum def_type_kind_t { - TYPE_NONE, - TYPE_STRUCT, - }; - - struct type_def_t; - - // A structure, representing a ++C type notation - struct type_t { - // The type definition of which this type is - // If NULL, then this type is unknown - // Feel free to scream at the user if this is NULL - type_def_t *def; - }; - // A structure, representing a field in a ++C struct - struct field_t { - // The type of which this field is - type_t type; - // The name of the field - const char *name; - // Whether or not the field is exported - bool is_exported; - }; - - // A structure, representing a ++C type (structs, classes, delegates and interfaces) - struct type_def_t { - // Whether or not this definition is exported - bool is_exported; - // The namespace of the type - namespace_name_t _namespace; - // The name of the type - const char *name; - // The version of the type (inherited from the module version) - version_t version; - // The location of the definition - location_t location; - - // The alignment padding from the start of the structures, in bytes - // Used either for efficiency sake or to store private fields (or both) - std::size_t align_size; - // A list of all the type's fields - std::vector fields; - }; -} From 1cbd17692923d15e5d1185c1b0d79f9672669982 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Mon, 5 Dec 2022 20:31:31 +0200 Subject: [PATCH 2/4] feat: add basic lang structure --- include/lang/common.hh | 57 ++++--- include/lang/module.hh | 162 ++++++++++++++++++++ src/compiler/treeifier/ast/parsers/group.cc | 34 ++-- src/lang/module.cc | 88 +++++++++++ 4 files changed, 298 insertions(+), 43 deletions(-) create mode 100644 include/lang/module.hh create mode 100644 src/lang/module.cc diff --git a/include/lang/common.hh b/include/lang/common.hh index 6d193c8..b60780c 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -1,5 +1,41 @@ #pragma once +#include + +namespace ppc::lang { + struct namespace_name_t : public std::vector { + using base = std::vector; + + int compare(const namespace_name_t &other) const; + + bool operator==(const namespace_name_t &other) const { return compare(other) == 0; } + bool operator!=(const namespace_name_t &other) const { return compare(other) != 0; } + bool operator<(const namespace_name_t &other) const { return compare(other) < 0; } + bool operator<=(const namespace_name_t &other) const { return compare(other) <= 0; } + bool operator>(const namespace_name_t &other) const { return compare(other) > 0; } + bool operator>=(const namespace_name_t &other) const { return compare(other) >= 0; } + + operator std::string() const { return to_string(); } + std::string to_string() const; + + namespace_name_t() { } + namespace_name_t(std::initializer_list segments): base(segments.begin(), segments.end()) { } + }; +} + +template <> +struct std::hash { + std::size_t operator()(const ppc::lang::namespace_name_t& k) const { + size_t res = 0; + + for (auto &el : k) { + res ^= std::hash()(el); + } + + return res; + } +}; + #include "utils/message.hh" #include "utils/location.hh" @@ -29,25 +65,6 @@ namespace ppc::lang { slocated_t() { } }; - struct namespace_name_t : public std::vector { - using base = std::vector; - - int compare(const namespace_name_t &other) const; - - bool operator==(const namespace_name_t &other) const { return compare(other) == 0; } - bool operator!=(const namespace_name_t &other) const { return compare(other) != 0; } - bool operator<(const namespace_name_t &other) const { return compare(other) < 0; } - bool operator<=(const namespace_name_t &other) const { return compare(other) <= 0; } - bool operator>(const namespace_name_t &other) const { return compare(other) > 0; } - bool operator>=(const namespace_name_t &other) const { return compare(other) >= 0; } - - operator std::string() const { return to_string(); } - std::string to_string() const; - - namespace_name_t() { } - namespace_name_t(std::initializer_list segments): base(segments.begin(), segments.end()) { } - }; - struct loc_namespace_name_t : public std::vector> { using base = std::vector>; @@ -74,4 +91,4 @@ namespace ppc::lang { messages::msg_stack_t ms; return is_identifier_valid(ms, { }, name); } -} +} \ No newline at end of file diff --git a/include/lang/module.hh b/include/lang/module.hh new file mode 100644 index 0000000..8205604 --- /dev/null +++ b/include/lang/module.hh @@ -0,0 +1,162 @@ +#include +#include +#include "lang/common.hh" + +namespace ppc::lang { + struct type_t { + namespace_name_t name; + size_t ptr_n; + }; + + struct statement_t { + private: + enum kind_t { + CALL, + STACK, + RETURN, + } kind; + union val_t { + namespace_name_t *call; + int64_t stack; + } val; + + ~statement_t(); + + statement_t(kind_t kind, val_t val) { + this->kind = kind; + this->val = val; + } + statement_t(kind_t kind) { + this->kind = kind; + } + + public: + bool is_call() const { return kind == CALL; } + bool is_stack() const { return kind == STACK; } + bool is_return() const { return kind == RETURN; } + + auto &call() const { + if (!is_call()) throw (std::string)"Statement is not a call."; + return val.call; + } + auto stack() const { + if (!is_call()) throw (std::string)"Statement is not a stack."; + return val.stack; + } + + static statement_t call(const namespace_name_t &func); + static statement_t stack(int64_t stack); + static statement_t ret(); + }; + + struct field_t { + type_t type; + }; + struct struct_t { + std::unordered_map fields; + }; + struct function_t { + std::unordered_map args; + type_t type; + + std::string get_signature(); + }; + + struct definition_t { + private: + enum { + FUNCTION, + STRUCT, + FIELD, + } kind; + union { + field_t *field; + struct_t *str; + function_t *func; + } val; + + public: + ~definition_t(); + definition_t(field_t val); + definition_t(struct_t val); + definition_t(function_t val); + definition_t(const definition_t &other); + + bool is_func() const { return kind == FUNCTION; } + bool is_struct() const { return kind == STRUCT; } + bool is_field() const { return kind == FIELD; } + + function_t &get_func(); + struct_t &get_struct(); + field_t &get_field(); + + const function_t &get_func() const { return ((definition_t&)*this).get_func(); } + const struct_t &get_struct() const { return ((definition_t&)*this).get_struct(); } + const field_t &get_field() const { return ((definition_t&)*this).get_field(); } + }; + + struct module_t { + private: + using fields_t = std::unordered_map; + using structs_t = std::unordered_map; + using funcs_t = std::unordered_map; + struct resolve_res_t { + namespace_name_t name; + definition_t def; + }; + public: + fields_t fields; + structs_t structs; + funcs_t funcs; + + const definition_t &def(namespace_name_t name); + void add_def(namespace_name_t name, const definition_t &def) { + if (def.is_field()) fields.emplace(name, def.get_field()); + if (def.is_func()) funcs.emplace(name, def.get_func()); + if (def.is_struct()) structs.emplace(name, def.get_struct()); + } + bool exists(namespace_name_t name) { + return + fields.find(name) != fields.end() || + structs.find(name) != structs.end() || + funcs.find(name) != funcs.end(); + } + }; + + template + struct resolve_res_t { + namespace_name_t name; + T value; + }; + + + bool resolve_name( + const std::vector &names, const std::set &imports, + const namespace_name_t &name, namespace_name_t &res + ); + + template + bool resolve_name_map( + const MapT &defs, const std::set &imports, + const namespace_name_t &name, namespace_name_t &res + ) { + std::vector names; + for (auto &it : defs) { + const namespace_name_t &val = it.first; + names.push_back(val); + } + return resolve_name(names, imports, name, res); + } + + template + bool resolve( + const MapT &defs, const std::set &imports, + const namespace_name_t &name, typename MapT::iterator &res + ) { + if (resolve_name_map(defs, imports, name, res.name)) { + res.value = defs.find(res.name)->second; + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/compiler/treeifier/ast/parsers/group.cc b/src/compiler/treeifier/ast/parsers/group.cc index 4cad173..bbe0f75 100644 --- a/src/compiler/treeifier/ast/parsers/group.cc +++ b/src/compiler/treeifier/ast/parsers/group.cc @@ -1,3 +1,4 @@ +#include "lang/module.hh" #include "compiler/treeifier/ast.hh" #include "compiler/treeifier/tokenizer.hh" #include "compiler/treeifier/ast/helper.hh" @@ -18,28 +19,7 @@ static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &nam name = conv::map_to_nmsp(res); return h.submit(false); } -template -static bool resolve_nmsp(ast_ctx_t &ctx, const lang::namespace_name_t &name, T begin, T end, lang::namespace_name_t &actual_name) { - for (auto it = begin; it != end; it++) { - const namespace_name_t &curr = it->first; - if (curr == name) { - actual_name = name; - return true; - } - } - for (const auto &import : ctx.imports) { - auto new_name = name; - new_name.insert(new_name.begin(), import.begin(), import.end()); - for (auto it = begin; it != end; it++) { - const namespace_name_t &curr = it->first; - if (curr == new_name) { - actual_name = name; - return true; - } - } - } - return false; -} + group_t &group_t::insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after) { if (parsers.find(name) != parsers.end()) { @@ -94,10 +74,18 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { if (h.ended()) return false; + std::set names; + + for (auto &import : ctx.imports) names.insert(import.strip_location()); + loc_namespace_name_t name; if (read_nmsp(ctx, h.i, name)) { namespace_name_t actual; - if (resolve_nmsp(ctx, name.strip_location(), named_parsers.begin(), named_parsers.end(), actual)) { + + if (resolve_name_map( + named_parsers, names, + name.strip_location(), actual + )) { auto parser = parsers.find(this->named_parsers.find(actual)->second); out["$_name"] = parser->first; if (h.parse(parser->second, out)) return h.submit(false); diff --git a/src/lang/module.cc b/src/lang/module.cc new file mode 100644 index 0000000..b14c4b1 --- /dev/null +++ b/src/lang/module.cc @@ -0,0 +1,88 @@ +#include "lang/module.hh" + +using namespace std::string_literals; +using namespace ppc::lang; + +definition_t::definition_t(function_t val) { + this->kind = FUNCTION; + this->val.func = new auto(val); +} +definition_t::definition_t(struct_t val) { + this->kind = STRUCT; + this->val.str = new auto(val); +} +definition_t::definition_t(field_t val) { + this->kind = FIELD; + this->val.field = new auto(val); +} +definition_t::definition_t(const definition_t &val) { + this->kind = val.kind; + switch (val.kind) { + case STRUCT: + this->val.str = new auto(*val.val.str); + break; + case FUNCTION: + this->val.func = new auto(*val.val.func); + break; + case FIELD: + this->val.field = new auto(*val.val.field); + break; + } +} + +definition_t::~definition_t() { + switch (this->kind) { + case FUNCTION: delete this->val.func; break; + case FIELD: delete this->val.field; break; + case STRUCT: delete this->val.str; break; + } +} + + +function_t &definition_t::get_func() { + if (!this->is_func()) throw "Definition is not a function."s; + return *this->val.func; +} +struct_t &definition_t::get_struct() { + if (!this->is_struct()) throw "Definition is not a struct."s; + return *this->val.str; +} +field_t &definition_t::get_field() { + if (!this->is_field()) throw "Definition is not a field."s; + return *this->val.field; +} + + + +statement_t statement_t::call(const namespace_name_t &func) { + return { CALL, { .call = new auto(func) }}; +} +statement_t statement_t::stack(int64_t stack) { + return { STACK, { .stack = stack }}; +} +statement_t statement_t::ret() { + return { RETURN }; +} + +bool ppc::lang::resolve_name( + const std::vector &names, const std::set &imports, + const namespace_name_t &name, namespace_name_t &res +) { + for (auto &curr : names) { + if (curr == name) { + res = curr; + return true; + } + } + for (auto &import : imports) { + auto new_name = name; + new_name.insert(new_name.begin(), import.begin(), import.end()); + for (auto &curr : names) { + if (curr == new_name) { + res = curr; + return true; + } + } + } + return false; +} \ No newline at end of file From 3c49434b125235c89b8042a97ba15e9aeb5bee05 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:01:09 +0200 Subject: [PATCH 3/4] feat: added struct parsing --- include/compiler/treeifier/ast.hh | 7 ++--- include/utils/data.hh | 4 +++ src/compiler/treeifier/ast/ast.cc | 31 +++++++++++--------- src/compiler/treeifier/ast/parsers/export.cc | 6 +++- src/compiler/treeifier/ast/parsers/field.cc | 2 ++ src/compiler/treeifier/ast/parsers/func.cc | 4 +++ src/compiler/treeifier/ast/parsers/group.cc | 22 +++----------- src/compiler/treeifier/ast/parsers/struct.cc | 24 +++++++++++++++ src/lsproj.cc | 1 - 9 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 src/compiler/treeifier/ast/parsers/struct.cc diff --git a/include/compiler/treeifier/ast.hh b/include/compiler/treeifier/ast.hh index ccfa3a3..78b53cd 100644 --- a/include/compiler/treeifier/ast.hh +++ b/include/compiler/treeifier/ast.hh @@ -26,10 +26,9 @@ namespace ppc::comp::tree::ast { std::set unnamed_parsers; std::map parsers; public: - group_t &insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after); - group_t &add_last(const std::string &name, parser_t parser); group_t &replace(const std::string &name, parser_t parser); - group_t &add_named(const std::string &name, parser_t parser, const lang::namespace_name_t &identifier); + group_t &add(const std::string &name, parser_t parser); + group_t &add(const std::string &name, const lang::namespace_name_t &identifier, parser_t parser); bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const; }; @@ -77,7 +76,7 @@ namespace ppc::comp::tree::ast { } parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp; - parser_func_t parse_func, parse_field, parse_export; + parser_func_t parse_func, parse_field, parse_export, parse_struct; parser_func_t parse_if, parse_while, parse_return, parse_break, parse_continue, parse_stat_comp; parser_func_t parse_exp_var, parse_exp_str_lit, parse_exp_int_lit, parse_exp_float_lit; } \ No newline at end of file diff --git a/include/utils/data.hh b/include/utils/data.hh index d1ff35a..a4e8b4e 100644 --- a/include/utils/data.hh +++ b/include/utils/data.hh @@ -99,6 +99,10 @@ namespace ppc::data { return values.find(key) != values.end(); } + void clear() { + values.clear(); + } + std::size_t size() const { return values.size(); } auto begin() const { return values.begin(); } diff --git a/src/compiler/treeifier/ast/ast.cc b/src/compiler/treeifier/ast/ast.cc index 578d987..34ff378 100644 --- a/src/compiler/treeifier/ast/ast.cc +++ b/src/compiler/treeifier/ast/ast.cc @@ -12,20 +12,23 @@ group_t &ast_ctx_t::group(const std::string &name) { ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): messages(messages), tokens(tokens) { group("$_exp_val") - .add_last("$_var", parse_exp_var) - .add_last("$_int", parse_exp_int_lit) - .add_last("$_string", parse_exp_str_lit); + .add("$_var", parse_exp_var) + .add("$_int", parse_exp_int_lit) + .add("$_string", parse_exp_str_lit); // .add_last("$_float", parse_exp_float_lit) group("$_stat") - .add_named("$_while", parse_while, { "while" }) - .add_named("$_if", parse_if, { "if" }) - .add_named("$_return", parse_return, { "return" }) - .add_named("$_break", parse_break, { "break" }) - .add_named("$_continue", parse_continue, { "continue" }) - .add_last("$_comp", parse_stat_comp) - .add_last("$_exp", parse_stat_exp); + .add("$_while", { "while" }, parse_while) + .add("$_if", { "if" }, parse_if) + .add("$_return", { "return" }, parse_return) + .add("$_break", { "break" }, parse_break) + .add("$_continue", { "continue" }, parse_continue) + .add("$_comp", parse_stat_comp) + .add("$_exp", parse_stat_exp); group("$_def") - .add_last("$_func", parse_func) - .add_named("$_export", parse_export, { "export" }) - .add_last("$_field", parse_field); -} \ No newline at end of file + .add("$_func", parse_func) + .add("$_struct", { "struct" }, parse_struct) + .add("$_field", parse_field); + group("$_struct_def") + .add("$_func", parse_func) + .add("$_field", parse_field); +} diff --git a/src/compiler/treeifier/ast/parsers/export.cc b/src/compiler/treeifier/ast/parsers/export.cc index dfd29a8..1076020 100644 --- a/src/compiler/treeifier/ast/parsers/export.cc +++ b/src/compiler/treeifier/ast/parsers/export.cc @@ -3,10 +3,14 @@ bool ast::parse_export(ast_ctx_t &ctx, size_t &res_i, map_t &out) { tree_helper_t h(ctx, res_i); + if (h.ended()) return false; + if (!h.curr().is_identifier("export")) return false; + h.advance("Unexpected end after export."); + if (out["exported"].is_true()) { ctx.messages.push(message_t(message_t::WARNING, "Export is alredy specified for this definition.", h.prev_loc())); } out["exported"] = true; - return ctx.group("$_def")(ctx, res_i, out); + return h.submit(false); } diff --git a/src/compiler/treeifier/ast/parsers/field.cc b/src/compiler/treeifier/ast/parsers/field.cc index a879a1d..b2815a5 100644 --- a/src/compiler/treeifier/ast/parsers/field.cc +++ b/src/compiler/treeifier/ast/parsers/field.cc @@ -5,6 +5,8 @@ bool ast::parse_field(ast_ctx_t &ctx, size_t &res_i, map_t &out) { if (h.ended()) return false; + h.parse(parse_export, out); + if (!h.parse(parse_identifier, out["name"].map({}))) return false; bool type = false, defval = false; diff --git a/src/compiler/treeifier/ast/parsers/func.cc b/src/compiler/treeifier/ast/parsers/func.cc index 1931aa8..e280a36 100644 --- a/src/compiler/treeifier/ast/parsers/func.cc +++ b/src/compiler/treeifier/ast/parsers/func.cc @@ -5,6 +5,8 @@ static bool parse_arg(ast_ctx_t &ctx, size_t &res_i, map_t &out) { if (h.ended()) return false; + h.parse(parse_export, out); + if (!h.parse(parse_identifier, out["name"].map({}))) return false; bool type = false, defval = false; @@ -34,6 +36,8 @@ bool ast::parse_func(ast_ctx_t &ctx, size_t &res_i, map_t &out) { if (h.ended()) return false; + h.parse(parse_export, out); + if (!h.parse(parse_identifier, out["name"].map({}))) return false; if (h.ended()) return false; if (!h.curr().is_operator(operator_t::PAREN_OPEN)) return false; diff --git a/src/compiler/treeifier/ast/parsers/group.cc b/src/compiler/treeifier/ast/parsers/group.cc index bbe0f75..410e511 100644 --- a/src/compiler/treeifier/ast/parsers/group.cc +++ b/src/compiler/treeifier/ast/parsers/group.cc @@ -21,22 +21,6 @@ static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &nam } -group_t &group_t::insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after) { - if (parsers.find(name) != parsers.end()) { - throw "The parser '" + name + "' is already in the group."; - } - - auto it = unnamed_parsers.find(relative_to); - if (it == unnamed_parsers.end()) { - throw "The parser '" + relative_to + "' isn't in the group or isn't unnamed."; - } - - if (after) it++; - - unnamed_parsers.insert(it, name); - - return *this; -} group_t &group_t::replace(const std::string &name, parser_t parser) { auto it = parsers.find(name); @@ -48,7 +32,7 @@ group_t &group_t::replace(const std::string &name, parser_t parser) { return *this; } -group_t &group_t::add_last(const std::string &name, parser_t parser) { +group_t &group_t::add(const std::string &name, parser_t parser) { if (parsers.find(name) != parsers.end()) { throw "The parser '" + name + "' is already in the group."; } @@ -58,7 +42,7 @@ group_t &group_t::add_last(const std::string &name, parser_t parser) { return *this; } -group_t &group_t::add_named(const std::string &name, parser_t parser, const lang::namespace_name_t &identifier) { +group_t &group_t::add(const std::string &name, const lang::namespace_name_t &identifier, parser_t parser) { if (parsers.find(name) != parsers.end()) { throw "The parser '" + name + "' is already in the group."; } @@ -87,6 +71,7 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { name.strip_location(), actual )) { auto parser = parsers.find(this->named_parsers.find(actual)->second); + out.clear(); out["$_name"] = parser->first; if (h.parse(parser->second, out)) return h.submit(false); else throw message_t::error("Unexpected construct specifier.", h.res_loc()); @@ -95,6 +80,7 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { for (auto name : unnamed_parsers) { out["$_name"] = name; + out.clear(); if (parsers.at(name)(ctx, i, out)) return true; } diff --git a/src/compiler/treeifier/ast/parsers/struct.cc b/src/compiler/treeifier/ast/parsers/struct.cc new file mode 100644 index 0000000..4ab0d94 --- /dev/null +++ b/src/compiler/treeifier/ast/parsers/struct.cc @@ -0,0 +1,24 @@ +#include "compiler/treeifier/ast/helper.hh" + +bool ast::parse_struct(ast_ctx_t &ctx, size_t &res_i, map_t &out) { + tree_helper_t h(ctx, res_i); + + if (h.ended()) return false; + + if (!h.parse(parse_identifier, out["name"].map({}))) return false; + + auto &content = out["content"].array({}); + + if (h.ended()) return false; + if (h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true); + if (!h.curr().is_operator(operator_t::BRACE_OPEN)) return false; + h.advance("Expected a definition, a closing brace, or a semicolon."); + + + while (!h.curr().is_operator(operator_t::BRACE_CLOSE)) { + h.throw_ended("Expected a definition or a closing brace."); + h.push_parse(ctx.group("$_struct_def"), content); + } + + return h.submit(true); +} diff --git a/src/lsproj.cc b/src/lsproj.cc index e133779..d32fe3e 100644 --- a/src/lsproj.cc +++ b/src/lsproj.cc @@ -1,7 +1,6 @@ #include #include #include -#include struct project_t { std::string output; From 06af7439d7b804bb70a8e2e0e0d94d2aa216df6f Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 19 Jan 2023 11:29:04 +0200 Subject: [PATCH 4/4] fix: add include string --- include/lang/common.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/include/lang/common.hh b/include/lang/common.hh index b60780c..ef7178a 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -1,6 +1,7 @@ #pragma once #include +#include namespace ppc::lang { struct namespace_name_t : public std::vector {