feat: add function parsing

This commit is contained in:
TopchetoEU 2022-10-22 15:19:05 +03:00
parent 17e5021fd8
commit d7ee0e3bb2
8 changed files with 145 additions and 24 deletions

View File

@ -27,6 +27,7 @@ namespace ppc::comp::tree::ast {
extern const parser_adder_t type_adder; extern const parser_adder_t type_adder;
extern const parser_adder_t exp_adder; extern const parser_adder_t exp_adder;
extern const parser_adder_t field_adder; extern const parser_adder_t field_adder;
extern const parser_adder_t func_adder;
extern const parser_adder_t var_adder; extern const parser_adder_t var_adder;
struct ast_ctx_t { struct ast_ctx_t {
@ -43,6 +44,7 @@ namespace ppc::comp::tree::ast {
private: private:
ast_ctx_t *parent; ast_ctx_t *parent;
public: public:
group_parser_t &operator[](const std::string &name);
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) { } group_proxy_t(ast_ctx_t *parent): parent(parent) { }
}; };
@ -58,7 +60,6 @@ namespace ppc::comp::tree::ast {
void add_parser(const parser_t *parser); void add_parser(const parser_t *parser);
void add_parser(const parser_t *parser, const std::string &group); void add_parser(const parser_t *parser, const std::string &group);
void add_parser(const parser_t *parser, const std::string &group, const namespace_name_t &name); void add_parser(const parser_t *parser, const std::string &group, const namespace_name_t &name);
void add_group(const std::string &name);
void add_parser(parser_adder_t factory) { factory(*this); } void add_parser(parser_adder_t factory) { factory(*this); }
@ -75,6 +76,7 @@ namespace ppc::comp::tree::ast {
add_parser(exp_adder); add_parser(exp_adder);
add_parser(var_adder); add_parser(var_adder);
add_parser(field_adder); add_parser(field_adder);
add_parser(func_adder);
return *this; return *this;
} }

View File

@ -73,6 +73,7 @@ namespace ppc::data {
}; };
static const value_t null{};
class map_t { class map_t {
private: private:

View File

@ -43,16 +43,16 @@ build: $(binary)
.SECONDEXPANSION: .SECONDEXPANSION:
$(binary): $$(call frdeps,$(mainmodule)) $$(call binaries,$(mainmodule)) $(binary): $$(call frdeps,$(mainmodule)) $$(call binaries,$(mainmodule))
$(call mkdir,$(dir $@)) $(call mkdir,$(dir $@))
echo Compiling executable '$(notdir $(binary))'...
$(CXX) $(flags) $(call binaries,$(mainmodule)) -o $@ $(ldflags) $(call ldeps,$(mainmodule)) -L$(bin) "-I$(inc)" $(CXX) $(flags) $(call binaries,$(mainmodule)) -o $@ $(ldflags) $(call ldeps,$(mainmodule)) -L$(bin) "-I$(inc)"
echo Compiling executable '$(notdir $(binary))'...
.SECONDEXPANSION: .SECONDEXPANSION:
$(bin)/lib$(lib)%$(so): $$(call frdeps,$$*) $$(call binaries,$$*) $(bin)/lib$(lib)%$(so): $$(call frdeps,$$*) $$(call binaries,$$*)
$(call mkdir,$(bin)) $(call mkdir,$(bin))
echo Compiling library '$(notdir $@)'...
$(CXX) -shared -fPIC $(flags) $(call binaries,$*) -o $@ $(ldflags) $(call ldeps,$*) -L$(bin) "-I$(inc)" $(CXX) -shared -fPIC $(flags) $(call binaries,$*) -o $@ $(ldflags) $(call ldeps,$*) -L$(bin) "-I$(inc)"
echo Compiling library '$(notdir $@)'...
$(bin)/tmp/%.o: $(src)/%.cc $(headers) $(bin)/tmp/%.o: $(src)/%.cc $(headers)
echo - Compiling '$*.cc'...
$(call mkdir,$(dir $@)) $(call mkdir,$(dir $@))
$(CXX) -fPIC -c $(flags) $< -o $@ $(CXX) -fPIC -c $(flags) $< -o $@
echo - Compiling '$*.cc'...

View File

@ -9,9 +9,19 @@ namespace ppc::comp::tree::ast {
return *it->second; return *it->second;
} }
group_parser_t &ast_ctx_t::group_proxy_t::operator[](const std::string &name) const { group_parser_t &ast_ctx_t::group_proxy_t::operator[](const std::string &name) const {
auto p = (group_parser_t*)&parent->parser[name]; auto it = parent->parsers.find(name);
if (parent->groups.find(p) == parent->groups.end()) throw "A parser '" + name + "' exists, but isn't a group."; if (it == parent->parsers.end()) {
return *p; auto p = new group_parser_t(name);
parent->parsers[name] = p;
parent->groups.emplace(p);
return *p;
}
else if (parent->groups.find((group_parser_t*)it->second) == parent->groups.end()) {
throw "A parser '" + name + "' exists, but isn't a group."s;
}
else {
return *(group_parser_t*)it->second;
}
} }
ast_ctx_t::~ast_ctx_t() { ast_ctx_t::~ast_ctx_t() {
@ -32,12 +42,6 @@ namespace ppc::comp::tree::ast {
add_parser(parser); add_parser(parser);
this->group[group].add(*parser, name); this->group[group].add(*parser, name);
} }
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);
}
data::map_t ast_ctx_t::parse(msg_stack_t &messages, std::vector<token_t> &tokens) { data::map_t ast_ctx_t::parse(msg_stack_t &messages, std::vector<token_t> &tokens) {
ast_ctx_t ctx(messages, tokens); ast_ctx_t ctx(messages, tokens);

View File

@ -282,4 +282,20 @@ class exp_parser_t : public parser_t {
public: exp_parser_t(): parser_t("$_exp") { } public: exp_parser_t(): parser_t("$_exp") { }
}; };
const parser_adder_t ppc::comp::tree::ast::exp_adder = [](ast_ctx_t &ctx) { ctx.add_parser(new exp_parser_t()); }; class exp_stat_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &i, map_t &res) const {
tree_helper_t h(ctx, i);
if (!h.parse("$_exp", res)) return false;
if (h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true);
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
return h.submit(false);
}
public: exp_stat_parser_t() : parser_t("$_exp_stat") { }
};
const parser_adder_t ppc::comp::tree::ast::exp_adder = [](ast_ctx_t &ctx) {
ctx.add_parser(new exp_parser_t());
ctx.add_parser(new exp_stat_parser_t(), "$_stat");
};

View File

@ -18,8 +18,6 @@ class field_parser_t : public parser_t {
type = true; type = true;
} }
if (h.curr().is_operator(operator_t::ASSIGN)) { if (h.curr().is_operator(operator_t::ASSIGN)) {
h.i++;
h.err("Default values are not yet supported.", 1);
h.advance(); h.advance();
h.force_parse("$_exp", "Expected an expression.", out["value"].map({})); h.force_parse("$_exp", "Expected an expression.", out["value"].map({}));
type = true; type = true;

View File

@ -0,0 +1,101 @@
#include "compiler/treeifier/ast/helper.hh"
class arg_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.advance();
h.force_parse("$_exp", "Expected an expression.", out["value"].map({}));
type = true;
}
if (!type && !defval) {
ctx.messages.push(message_t::error("Expected a type or a default value.", h.loc(1)));
}
return h.submit(false);
}
public: arg_parser_t(): parser_t("$_func_arg") {}
};
class func_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;
if (h.ended()) return false;
if (!h.curr().is_operator(operator_t::PAREN_OPEN)) return false;
h.advance("Expected a closing paren or a parameter.");
auto &params = out["params"].array({});
auto &content = out["content"].array({});
while (true) {
if (h.curr().is_operator(operator_t::PAREN_CLOSE)) {
h.advance("Expected a function body.");
break;
}
h.force_push_parse("$_func_arg", "Expected a parameter.", params);
if (h.curr().is_operator(operator_t::COMMA)) {
h.advance("Expected a parameter.");
}
}
if (h.curr().is_operator(operator_t::COLON)) {
h.advance("Expected a type.");
h.force_parse("$_type", "Expected a type", out["type"].map({}));
}
if (h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true);
else if (h.curr().is_operator(operator_t::LAMBDA)) {
h.advance("Expected an expression.");
map_t exp;
h.force_parse("$_exp", "Expected an expression.", exp);
content.push_back({
{ "$_name", "$_return" },
{ "content", exp },
});
return h.submit(false);
}
else if (h.curr().is_operator(operator_t::BRACE_OPEN)) {
h.advance("Expected a statement.");
while (true) {
if (h.curr().is_operator(operator_t::BRACE_CLOSE)) {
return h.submit(true);
}
h.force_push_parse("$_stat", "Expected an expression.", content);
}
}
else {
ctx.messages.push(message_t::error("Expected a semicolon, brace open or a lambda operator.", h.loc(1)));
return h.submit(false);
}
return h.submit(true);
}
public: func_parser_t(): parser_t("$_func") { }
};
const parser_adder_t ppc::comp::tree::ast::func_adder = [](ast_ctx_t &ctx) {
ctx.add_parser(new func_parser_t(), "$_def");
ctx.add_parser(new arg_parser_t());
};

View File

@ -18,7 +18,7 @@ class nmsp_def_parser_t : public parser_t {
return h.submit(true); return h.submit(true);
} }
public: nmsp_def_parser_t(): parser_t("$_nmsp_def") { } public: nmsp_def_parser_t(): parser_t("$_nmsp") { }
}; };
class import_parser_t : public parser_t { class import_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) const { bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) const {
@ -46,15 +46,16 @@ class glob_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const { bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const {
tree_helper_t h(ctx, res_i); tree_helper_t h(ctx, res_i);
return h.parse("$_exp", out);
if (h.ended()) return true; if (h.ended()) return true;
if (nmsp_def_parser(ctx, h.i, (out["namespace"] = map_t()).map())) { if (nmsp_def_parser(ctx, h.i, out["namespace"].map({}))) {
ctx.nmsp = conv::map_to_nmsp(out["namespace"].map()); ctx.nmsp = conv::map_to_nmsp(out["namespace"].map());
} }
else {
out["namespace"] = data::null;
}
auto &imports = (out["imports"] = array_t()).array(); auto &imports = out["imports"].array({});
auto &contents = (out["content"] = array_t()).array(); auto &contents = out["content"].array({});
while (true) { while (true) {
map_t map; map_t map;
@ -83,7 +84,5 @@ public:
}; };
const parser_adder_t ppc::comp::tree::ast::glob_adder = [](ast_ctx_t &ctx) { const parser_adder_t ppc::comp::tree::ast::glob_adder = [](ast_ctx_t &ctx) {
ctx.add_group("$_def");
ctx.add_group("$_exp_val");
ctx.add_parser(new glob_parser_t()); ctx.add_parser(new glob_parser_t());
}; };