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;