From 7a98dfa825b4c0f7acdb50663a5385ff7b80fa64 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:49:49 +0300 Subject: [PATCH] feat: add if, else, return, break, continue and compounds stat --- include/compiler/treeifier/ast.hh | 1 + src/compiler/treeifier/ast/ast.cc | 6 ++ src/compiler/treeifier/ast/parsers/stat.cc | 98 ++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 src/compiler/treeifier/ast/parsers/stat.cc diff --git a/include/compiler/treeifier/ast.hh b/include/compiler/treeifier/ast.hh index 6594c24..ccfa3a3 100644 --- a/include/compiler/treeifier/ast.hh +++ b/include/compiler/treeifier/ast.hh @@ -78,5 +78,6 @@ 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_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/src/compiler/treeifier/ast/ast.cc b/src/compiler/treeifier/ast/ast.cc index 912ed86..578d987 100644 --- a/src/compiler/treeifier/ast/ast.cc +++ b/src/compiler/treeifier/ast/ast.cc @@ -17,6 +17,12 @@ ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): messa .add_last("$_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); group("$_def") .add_last("$_func", parse_func) diff --git a/src/compiler/treeifier/ast/parsers/stat.cc b/src/compiler/treeifier/ast/parsers/stat.cc new file mode 100644 index 0000000..4548797 --- /dev/null +++ b/src/compiler/treeifier/ast/parsers/stat.cc @@ -0,0 +1,98 @@ +#include "compiler/treeifier/ast/helper.hh" + +bool ast::parse_if(ast_ctx_t &ctx, size_t &res_i, map_t &out) { + tree_helper_t h(ctx, res_i); + + h.throw_ended(); + if (!h.curr("Expected open parens after if keyword.").is_operator(operator_t::PAREN_OPEN)) { + throw message_t::error("Expected open parens after if keyword.", h.loc(1)); + } + + h.advance("Expected an expression."); + h.force_parse(parse_exp, "Expected an expression.", out["condition"].map({})); + + if (!h.curr("Expected closed parens.").is_operator(operator_t::PAREN_CLOSE)) { + throw message_t::error("Expected closed parens.", h.loc(1)); + } + + h.advance("Expected a statement."); + h.force_parse(ctx.group("$_stat"), "Expected a statement.", out["if"].map({})); + + if (h.ended() || !h.curr().is_identifier("else")) return h.submit(false); + + h.advance("Expected a statement."); + h.force_parse(ctx.group("$_stat"), "Expected a statement.", out["else"].map({})); + + return h.submit(false); +} + +bool ast::parse_while(ast_ctx_t &ctx, size_t &res_i, map_t &out) { + tree_helper_t h(ctx, res_i); + + h.throw_ended(); + if (!h.curr("Expected open parens after while keyword.").is_operator(operator_t::PAREN_OPEN)) { + throw message_t::error("Expected open parens after while keyword.", h.loc(1)); + } + + h.advance("Expected an expression."); + h.force_parse(parse_exp, "Expected an expression.", out["condition"].map({})); + + if (!h.curr("Expected closed parens.").is_operator(operator_t::PAREN_CLOSE)) { + throw message_t::error("Expected closed parens.", h.loc(1)); + } + + h.advance("Expected a statement."); + h.force_parse(ctx.group("$_stat"), "Expected a statement.", out["while"].map({})); + + return h.submit(false); +} + +bool ast::parse_return(ast_ctx_t &ctx, size_t &res_i, map_t &out) { + tree_helper_t h(ctx, res_i); + + h.advance("Expected an expression."); + h.force_parse(parse_exp, "Expected an expression.", out["condition"].map({})); + + if (!h.curr("Expected a semicolon.").is_operator(operator_t::SEMICOLON)) { + throw message_t::error("Expected a semicolon.", h.loc(1)); + } + + return h.submit(true); +} + +bool ast::parse_break(ast_ctx_t &ctx, size_t &res_i, map_t &out) { + tree_helper_t h(ctx, res_i); + + if (!h.curr("Expected a semicolon.").is_operator(operator_t::SEMICOLON)) { + throw message_t::error("Expected a semicolon.", h.loc(1)); + } + + return h.submit(true); +} + +bool ast::parse_continue(ast_ctx_t &ctx, size_t &res_i, map_t &out) { + tree_helper_t h(ctx, res_i); + + if (!h.curr("Expected a semicolon.").is_operator(operator_t::SEMICOLON)) { + throw message_t::error("Expected a semicolon.", h.loc(1)); + } + + return h.submit(true); +} + +bool ast::parse_stat_comp(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_operator(operator_t::BRACE_OPEN)) return false; + h.advance("Expected a statement or a closing brace."); + + auto &content = out["content"].array({}); + + while (!h.curr().is_operator(operator_t::BRACE_CLOSE)) { + h.throw_ended("Expected a statement or a closing brace."); + h.push_parse(ctx.group("$_stat"), content); + } + + return h.submit(true); +} \ No newline at end of file