From b8594aecd666a2faf5eb1eaddfec4bd1ea596bca Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 20 Jan 2023 16:43:52 +0200 Subject: [PATCH 01/14] refactor: fix formatting --- include/compiler/treeifier/ast.hh | 45 +++-- src/compiler/treeifier/ast/ast.cc | 7 +- src/compiler/treeifier/ast/conv.cc | 2 +- src/compiler/treeifier/ast/parsers.cc | 0 src/compiler/treeifier/ast/parsers/exp.cc | 20 +-- src/compiler/treeifier/ast/parsers/glob.cc | 1 - src/compiler/treeifier/lexer.cc | 9 +- src/compiler/treeifier/operators.cc | 2 +- src/compiler/treeifier/tokenizer.cc | 6 +- src/lang/common.cc | 4 +- src/lang/module.cc | 17 +- src/lsproj.cc | 29 ++-- src/main/main.cc | 188 ++++++++++----------- src/main/opions.hh | 8 +- src/main/options.cc | 2 +- src/utils/data.cc | 23 +-- src/utils/location.cc | 8 +- src/utils/message.cc | 32 ++-- src/utils/strings.cc | 6 +- src/utils/threading.cc | 8 +- 20 files changed, 230 insertions(+), 187 deletions(-) delete mode 100644 src/compiler/treeifier/ast/parsers.cc diff --git a/include/compiler/treeifier/ast.hh b/include/compiler/treeifier/ast.hh index 78b53cd..e998f67 100644 --- a/include/compiler/treeifier/ast.hh +++ b/include/compiler/treeifier/ast.hh @@ -1,14 +1,15 @@ #pragma once -#include -#include #include -#include -#include #include +#include +#include +#include +#include + #include "compiler/treeifier/tokenizer.hh" -#include "utils/data.hh" #include "lang/common.hh" +#include "utils/data.hh" using namespace std::string_literals; using namespace ppc; @@ -17,15 +18,15 @@ using namespace ppc::messages; namespace ppc::comp::tree::ast { struct ast_ctx_t; - using parser_func_t = bool (ast_ctx_t &ctx, size_t &res_i, data::map_t &out); - using parser_t = parser_func_t*; + using parser_func_t = bool(ast_ctx_t &ctx, size_t &res_i, data::map_t &out); + using parser_t = parser_func_t *; class group_t { - private: + private: std::map named_parsers; std::set unnamed_parsers; std::map parsers; - public: + public: group_t &replace(const std::string &name, parser_t parser); 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); @@ -34,9 +35,9 @@ namespace ppc::comp::tree::ast { }; struct ast_ctx_t { - private: + private: std::unordered_map groups; - public: + public: msg_stack_t &messages; std::vector &tokens; std::set imports; @@ -73,6 +74,28 @@ namespace ppc::comp::tree::ast { data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp); loc_namespace_name_t map_to_nmsp(const data::map_t &map); + } // namespace conv + + class construct_t { + public: + virtual const std::string &name() const = 0; + }; + + class parser_t { + public: + virtual bool parse(ast_ctx_t &ctx, size_t &res_i, construct_t *&out) const = 0; + virtual bool simplify(ast_ctx_t &ctx, size_t &res_i, const construct_t *global, const construct_t *container, const construct_t *current) const = 0; + }; + + namespace constr { + class glob_con_t: public construct_t { + const std::string &name() const { return "$_glob"s; } + bool parse(ast_ctx_t &ctx, size_t &res_i, construct_t *&out) const; + }; + } + + namespace parsers { + } parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp; diff --git a/src/compiler/treeifier/ast/ast.cc b/src/compiler/treeifier/ast/ast.cc index 34ff378..e875f59 100644 --- a/src/compiler/treeifier/ast/ast.cc +++ b/src/compiler/treeifier/ast/ast.cc @@ -6,16 +6,17 @@ using namespace ppc::lang; using namespace ppc::comp::tree::ast; group_t &ast_ctx_t::group(const std::string &name) { - if (groups.find(name) == groups.end()) return groups[name] = { }; + if (groups.find(name) == groups.end()) return groups[name] = {}; else return groups[name]; } -ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): messages(messages), tokens(tokens) { +ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): + messages(messages), tokens(tokens) { group("$_exp_val") .add("$_var", parse_exp_var) .add("$_int", parse_exp_int_lit) .add("$_string", parse_exp_str_lit); - // .add_last("$_float", parse_exp_float_lit) + // .add_last("$_float", parse_exp_float_lit) group("$_stat") .add("$_while", { "while" }, parse_while) .add("$_if", { "if" }, parse_if) diff --git a/src/compiler/treeifier/ast/conv.cc b/src/compiler/treeifier/ast/conv.cc index f3a688d..41fd248 100644 --- a/src/compiler/treeifier/ast/conv.cc +++ b/src/compiler/treeifier/ast/conv.cc @@ -1,5 +1,5 @@ -#include #include "compiler/treeifier/ast.hh" +#include namespace ppc::comp::tree::ast::conv { data::map_t identifier_to_map(const located_t &loc) { diff --git a/src/compiler/treeifier/ast/parsers.cc b/src/compiler/treeifier/ast/parsers.cc deleted file mode 100644 index e69de29..0000000 diff --git a/src/compiler/treeifier/ast/parsers/exp.cc b/src/compiler/treeifier/ast/parsers/exp.cc index 700d098..929d85a 100644 --- a/src/compiler/treeifier/ast/parsers/exp.cc +++ b/src/compiler/treeifier/ast/parsers/exp.cc @@ -1,6 +1,6 @@ #include "compiler/treeifier/ast/helper.hh" -#include #include +#include enum precedence_t { NONE, @@ -170,10 +170,7 @@ bool pop_call(size_t n, location_t loc, std::vector> &op_st bool pop_until(const op_data_t &data, tree_helper_t &h, std::vector> &op_stack, array_t &res) { while (!op_stack.empty()) { auto &back_data = op_stack.back(); - if (data.assoc ? - back_data.precedence >= data.precedence : - back_data.precedence > data.precedence - ) break; + if (data.assoc ? back_data.precedence >= data.precedence : back_data.precedence > data.precedence) break; if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator."); } @@ -188,7 +185,9 @@ bool ast::parse_exp_int_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) { if (h.curr().is_int_literal()) { auto &arr = out["content"].array({}); - for (auto b : h.curr().literal()) arr.push_back((float)b); + for (auto b : h.curr().literal()) { + arr.push_back((float)b); + } out["location"] = conv::loc_to_map(h.loc()); return h.submit(true); } @@ -200,7 +199,9 @@ bool ast::parse_exp_str_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) { if (h.curr().is_str_literal()) { auto &arr = out["content"].array({}); - for (auto b : h.curr().literal()) arr.push_back((float)b); + for (auto b : h.curr().literal()) { + arr.push_back((float)b); + } out["location"] = conv::loc_to_map(h.loc()); return h.submit(true); } @@ -301,9 +302,8 @@ bool ast::parse_exp(ast_ctx_t &ctx, size_t &res_i, map_t &out) { }; h.force_parse(parse_identifier, "Expected an identifier.", member_access["name"].map({})); member_access["location"] = conv::loc_to_map( - conv::map_to_loc(member_access["name"].map()["location"].string()).intersect( - conv::map_to_loc(res.back().map()["location"].string()) - ) + conv::map_to_loc(member_access["name"].map()["location"].string()) + .intersect(conv::map_to_loc(res.back().map()["location"].string())) ); res.pop_back(); res.push_back(member_access); diff --git a/src/compiler/treeifier/ast/parsers/glob.cc b/src/compiler/treeifier/ast/parsers/glob.cc index 2b8021a..a28053f 100644 --- a/src/compiler/treeifier/ast/parsers/glob.cc +++ b/src/compiler/treeifier/ast/parsers/glob.cc @@ -1,6 +1,5 @@ #include "compiler/treeifier/ast.hh" #include "compiler/treeifier/ast/helper.hh" -// #include "./type.cc" using namespace ppc::comp::tree::ast; diff --git a/src/compiler/treeifier/lexer.cc b/src/compiler/treeifier/lexer.cc index 0127d64..b12b3b9 100644 --- a/src/compiler/treeifier/lexer.cc +++ b/src/compiler/treeifier/lexer.cc @@ -1,6 +1,6 @@ -#include #include "compiler/treeifier/lexer.hh" #include "utils/message.hh" +#include using namespace ppc; using namespace ppc::messages; @@ -73,7 +73,7 @@ static res_t lexlet_oct(char c, std::vector &tok) { if (isoct(c)) return lexer_none(); else if (isdigit(c)) throw message_t::error("An octal literal may only contain octal digits."); else return lexer_end(token_t::OCT_LITERAL); -}; +}; static res_t lexlet_float(char c, std::vector &tok) { if (isdigit(c)) return lexer_none(); else return lexer_end(token_t::FLOAT_LITERAL); @@ -193,7 +193,7 @@ std::vector token_t::parse_many(ppc::messages::msg_stack_t &msg_stack, } } } - catch (const messages::message_t &msg) { + catch (const messages::message_t &msg) { throw message_t(msg.level, msg.content, location_t(filename, line, start, i - curr_token.size(), curr_token.size())); } } @@ -214,7 +214,8 @@ std::vector token_t::parse_file(ppc::messages::msg_stack_t &msg_stack, std::vector contents; int c; - while ((c = f.get()) != EOF) contents.push_back(c); + while ((c = f.get()) != EOF) + contents.push_back(c); return parse_many(msg_stack, filename, std::string { contents.begin(), contents.end() }); } diff --git a/src/compiler/treeifier/operators.cc b/src/compiler/treeifier/operators.cc index b03bd90..584c264 100644 --- a/src/compiler/treeifier/operators.cc +++ b/src/compiler/treeifier/operators.cc @@ -1,5 +1,5 @@ -#include #include "compiler/treeifier/tokenizer.hh" +#include using namespace ppc::comp::tree; using namespace ppc::comp; diff --git a/src/compiler/treeifier/tokenizer.cc b/src/compiler/treeifier/tokenizer.cc index e603d86..2da0e7d 100644 --- a/src/compiler/treeifier/tokenizer.cc +++ b/src/compiler/treeifier/tokenizer.cc @@ -1,7 +1,7 @@ -#include -#include -#include "compiler/treeifier/tokenizer.hh" #include "compiler/treeifier/lexer.hh" +#include "compiler/treeifier/tokenizer.hh" +#include +#include using namespace ppc; using namespace messages; diff --git a/src/lang/common.cc b/src/lang/common.cc index bf4bd70..7c5a004 100644 --- a/src/lang/common.cc +++ b/src/lang/common.cc @@ -1,6 +1,5 @@ - -#include #include "lang/common.hh" +#include namespace ppc::lang { std::string loc_namespace_name_t::to_string() const { @@ -57,4 +56,3 @@ namespace ppc::lang { return res; } } - diff --git a/src/lang/module.cc b/src/lang/module.cc index b14c4b1..1b91993 100644 --- a/src/lang/module.cc +++ b/src/lang/module.cc @@ -32,9 +32,15 @@ definition_t::definition_t(const definition_t &val) { 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; + case FUNCTION: + delete this->val.func; + break; + case FIELD: + delete this->val.field; + break; + case STRUCT: + delete this->val.str; + break; } } @@ -53,12 +59,11 @@ field_t &definition_t::get_field() { } - statement_t statement_t::call(const namespace_name_t &func) { - return { CALL, { .call = new auto(func) }}; + return { CALL, { .call = new auto(func) } }; } statement_t statement_t::stack(int64_t stack) { - return { STACK, { .stack = stack }}; + return { STACK, { .stack = stack } }; } statement_t statement_t::ret() { return { RETURN }; diff --git a/src/lsproj.cc b/src/lsproj.cc index d32fe3e..f1d3dc7 100644 --- a/src/lsproj.cc +++ b/src/lsproj.cc @@ -1,6 +1,9 @@ -#include #include #include +#include +#include + +using namespace std::string_literals; struct project_t { std::string output; @@ -8,7 +11,7 @@ struct project_t { }; std::string read_str(std::istream &f, const std::string &skip_chars, const std::string &end_chars, int &end_char) { - std::vector res { }; + std::vector res {}; int c; while (true) { @@ -49,10 +52,10 @@ project_t read_project(std::istream &f) { int end_ch; std::string name = read_str(f, " \v\t\r\n", "\n", end_ch); std::size_t cap = 16, n = 0; - std::vector deps { }; + std::vector deps {}; if (name.length() == 0) { - throw (std::string)"The name of a project may not be empty."; + throw "The name of a project may not be empty."s; } if (end_ch == -1) { @@ -63,14 +66,14 @@ project_t read_project(std::istream &f) { } if (name.find(',') != std::string::npos || name.find(' ') != std::string::npos) { - throw (std::string)"The name of a project may not contain spaces or commas."; + throw "The name of a project may not contain spaces or commas."s; } while (true) { std::string dep = read_str(f, " \v\t\r\n", ",\n", end_ch); if (dep.find(' ') != std::string::npos) { - throw (std::string)"The name of a dependency may not contain spaces."; + throw "The name of a dependency may not contain spaces."s; } if (dep.length()) { @@ -90,38 +93,38 @@ void print_err(const std::string &error, const std::string &context) { std::cerr << context << ": " << error; } -int main(int argc, const char* argv[]) { +int main(int argc, const char *argv[]) { std::string proj_name = ""; try { argc--; argv++; if (argc != 3) { - throw (std::string)"Incorrect usage. Syntax: [src-dir] [project-name] [output|deps]."; + throw "Incorrect usage. Syntax: [src-dir] [project-name] [output|deps]."s; } - std::string proj_path = (std::string)argv[0] + "/" + argv[1] + ".proj"; + std::string proj_path = (std::string) argv[0] + "/" + argv[1] + ".proj"; proj_name = argv[1]; std::ifstream f { proj_path, std::ios_base::in }; if (!f.is_open()) { - throw (std::string)"The project '" + argv[1] +"' doesn't exist."; + throw "The project '"s + argv[1] + "' doesn't exist."s; } project_t project = read_project(f); f.close(); - if ((std::string)argv[2] == "output") { + if ((std::string) argv[2] == "output") { std::cout << project.output; } - else if ((std::string)argv[2] == "deps") { + else if ((std::string) argv[2] == "deps") { for (std::string dep : project.deps) { std::cout << dep << " "; } } else { - throw (std::string)"Invalid command given. Available commands: output, deps."; + throw "Invalid command given. Available commands: output, deps."s; } std::cout << std::endl; diff --git a/src/main/main.cc b/src/main/main.cc index 5a9a16b..6e9a029 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -8,25 +8,25 @@ #define DISABLE_NEWLINE_AUTO_RETURN 0x8 #endif -#include #include +#include #undef ERROR #undef INFO #endif -#include -#include -#include -#include -#include "utils/threading.hh" -#include "utils/strings.hh" -#include "utils/json.hh" +#include "./opions.hh" +#include "compiler/treeifier/ast.hh" #include "compiler/treeifier/lexer.hh" #include "compiler/treeifier/tokenizer.hh" -#include "compiler/treeifier/ast.hh" -#include "./opions.hh" +#include "utils/json.hh" +#include "utils/strings.hh" +#include "utils/threading.hh" +#include +#include +#include +#include using std::cout; using std::size_t; @@ -35,79 +35,79 @@ using namespace ppc::comp::tree; using namespace ppc::comp::tree::ast; void add_flags(options::parser_t &parser) { - parser.add_flag({ - .name = "version", - .shorthands = "v", - .description = "Displays version and license agreement of this binary", - .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { - cout << "++C compiler\n" - << " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD - #if WINDOWS - << " (Windows)" - #elif LINUX + parser.add_flag({ .name = "version", + .shorthands = "v", + .description = "Displays version and license agreement of this binary", + .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { + cout << "++C compiler\n" + << " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD +#if WINDOWS + << " (Windows)" +#elif LINUX << " (Linux)" - #endif - << "\n" - << " License: MIT Copyright (C) TopchetoEU\n"; - exit(0); - } - }); - parser.add_flag({ - .name = "help", - .shorthands = "h", - .description = "Displays a list of all flags and their meaning", - .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { - cout << "Usage: ...flags ...files\n\n" - << "Flags and file names can be interlaced\n" - << "Flags will execute in the order they're written, then compilation begins\n\n" - << "Flags:\n"; - - for (const auto &flag : parser) { - std::stringstream buff; - buff << " --" << flag.name; - - if (flag.match_type) buff << "=..."; - if (flag.shorthands.size()) { - buff << " ("; - bool first = true; - for (char shorthand : flag.shorthands) { - if (!first) buff << ","; - else first = false; - - buff << " -"; - buff << std::string { shorthand }; - } - buff << ")"; - } - - buff << " "; - - cout << buff.str(); - size_t n = buff.str().length(); - - if (flag.description.size()) { - const size_t padding = 24; - const size_t msg_width = 80 - padding; - - for (size_t i = 0; i < padding - n; i++) cout << ' '; - - int len = flag.description.length(); - - for (size_t i = 0; i < len / msg_width; i++) { - for (size_t j = 0; j < msg_width; j++) cout << flag.description[i * msg_width + j]; - cout << std::endl; - for (size_t j = 0; j < padding; j++) cout << ' '; - } - - int remainder = len % msg_width; - - for (int i = 0; i < remainder; i++) cout << flag.description[len - remainder + i]; - } - - printf("\n"); - } - } - }); +#endif + << "\n" + << " License: MIT Copyright (C) TopchetoEU\n"; + exit(0); + } }); + parser.add_flag({ .name = "help", + .shorthands = "h", + .description = "Displays a list of all flags and their meaning", + .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { + cout << "Usage: ...flags ...files\n\n" + << "Flags and file names can be interlaced\n" + << "Flags will execute in the order they're written, then compilation begins\n\n" + << "Flags:\n"; + + for (const auto &flag : parser) { + std::stringstream buff; + buff << " --" << flag.name; + + if (flag.match_type) buff << "=..."; + if (flag.shorthands.size()) { + buff << " ("; + bool first = true; + for (char shorthand : flag.shorthands) { + if (!first) buff << ","; + else first = false; + + buff << " -"; + buff << std::string { shorthand }; + } + buff << ")"; + } + + buff << " "; + + cout << buff.str(); + size_t n = buff.str().length(); + + if (flag.description.size()) { + const size_t padding = 24; + const size_t msg_width = 80 - padding; + + for (size_t i = 0; i < padding - n; i++) + cout << ' '; + + int len = flag.description.length(); + + for (size_t i = 0; i < len / msg_width; i++) { + for (size_t j = 0; j < msg_width; j++) + cout << flag.description[i * msg_width + j]; + cout << std::endl; + for (size_t j = 0; j < padding; j++) + cout << ' '; + } + + int remainder = len % msg_width; + + for (int i = 0; i < remainder; i++) + cout << flag.description[len - remainder + i]; + } + + printf("\n"); + } + } }); parser.add_flag({ .name = "silent", .shorthands = "qs", @@ -118,27 +118,25 @@ void add_flags(options::parser_t &parser) { .description = "Sets a lower limit of messages that will print. Accepted values: 'all', 'debug', 'suggestion', 'info', 'warning', 'error', 'none'", .match_type = options::MATCH_PREFIX, }); - parser.add_flag({ - .name = "print-what", - .description = "Prints a 'what?' type of message (you'll see)", - .match_type = options::MATCH_PREFIX, - .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { - global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL.")); - } - }); + parser.add_flag({ .name = "print-what", + .description = "Prints a 'what?' type of message (you'll see)", + .match_type = options::MATCH_PREFIX, + .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { + global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL.")); + } }); } int main(int argc, const char *argv[]) { - #ifdef WINDOWS +#ifdef WINDOWS HANDLE handleOut = GetStdHandle(STD_OUTPUT_HANDLE); DWORD consoleMode; GetConsoleMode(handleOut, &consoleMode); consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; consoleMode |= DISABLE_NEWLINE_AUTO_RETURN; SetConsoleMode(handleOut, consoleMode); - #endif +#endif - std::vector args{ argv + 1, argv + argc }; + std::vector args { argv + 1, argv + argc }; std::vector files; messages::msg_stack_t msg_stack; @@ -170,7 +168,7 @@ int main(int argc, const char *argv[]) { catch (const messages::message_t &msg) { msg_stack.push(msg); } - #ifndef PROFILE_debug +#ifndef PROFILE_debug catch (const std::string &msg) { msg_stack.push(message_t::error(msg)); } @@ -178,7 +176,7 @@ int main(int argc, const char *argv[]) { std::cout << std::endl; msg_stack.push(message_t::error("A fatal error occurred.")); } - #endif +#endif msg_stack.print(std::cout, messages::message_t::DEBUG, true); diff --git a/src/main/opions.hh b/src/main/opions.hh index f91f100..22ae0f4 100644 --- a/src/main/opions.hh +++ b/src/main/opions.hh @@ -1,8 +1,8 @@ #pragma once -#include -#include "utils/message.hh" #include "utils/data.hh" +#include "utils/message.hh" +#include namespace ppc::options { enum flag_match_type_t { @@ -21,9 +21,9 @@ namespace ppc::options { }; struct parser_t { - private: + private: std::vector flags; - public: + public: void add_flag(const flag_t &flag); void clear_flags(); diff --git a/src/main/options.cc b/src/main/options.cc index 9328a1c..f8d655b 100644 --- a/src/main/options.cc +++ b/src/main/options.cc @@ -1,5 +1,5 @@ -#include #include "./opions.hh" +#include using namespace ppc; diff --git a/src/utils/data.cc b/src/utils/data.cc index 39bddb7..d86e213 100644 --- a/src/utils/data.cc +++ b/src/utils/data.cc @@ -1,4 +1,7 @@ #include "utils/data.hh" +#include + +using namespace std::string_literals; namespace ppc::data { bool value_t::is_null() const { @@ -44,45 +47,45 @@ namespace ppc::data { array_t &value_t::array() { if (is_array()) return *val.arr; - else throw (std::string)"The value isn't an array."; + else throw "The value isn't an array."s; } map_t &value_t::map() { if (is_map()) return *val.map; - else throw (std::string)"The value isn't a map."; + else throw "The value isn't a map."s; } number_t &value_t::number() { if (is_number()) return val.num; - else throw (std::string)"The value isn't a number."; + else throw "The value isn't a number."s; } string_t &value_t::string() { if (is_string()) return *val.str; - else throw (std::string)"The value isn't a string."; + else throw "The value isn't a string."s; } bool_t &value_t::boolean() { if (is_bool()) return val.bl; - else throw (std::string)"The value isn't a bool."; + else throw "The value isn't a bool."s; } const array_t &value_t::array() const { if (is_array()) return *val.arr; - else throw (std::string)"The value isn't an array."; + else throw "The value isn't an array."s; } const map_t &value_t::map() const { if (is_map()) return *val.map; - else throw (std::string)"The value isn't a map."; + else throw "The value isn't a map."s; } number_t value_t::number() const { if (is_number()) return val.num; - else throw (std::string)"The value isn't a number."; + else throw "The value isn't a number."s; } const string_t &value_t::string() const { if (is_string()) return *val.str; - else throw (std::string)"The value isn't a string."; + else throw "The value isn't a string."s; } bool_t value_t::boolean() const { if (is_bool()) return val.bl; - else throw (std::string)"The value isn't a bool."; + else throw "The value isn't a bool."s; } value_t::value_t() { diff --git a/src/utils/location.cc b/src/utils/location.cc index 9169ddd..03cfecf 100644 --- a/src/utils/location.cc +++ b/src/utils/location.cc @@ -39,7 +39,7 @@ location_t location_t::intersect(location_t other) const { location_t a = *this; location_t b = other; - if (a.start == -1u || b.start == -1u) return { }; + if (a.start == -1u || b.start == -1u) return {}; if (a.start > b.start) return other.intersect(*this); @@ -67,7 +67,6 @@ bool location_t::operator==(const location_t &other) const { } - std::string empty = ""; location_t::location_t(): @@ -84,11 +83,12 @@ location_t::location_t(const std::string &filename, std::size_t line, std::size_ location_t(filename, line, start, code_start, -1) { } location_t::location_t(std::size_t line, std::size_t start, std::size_t code_start, std::size_t length): location_t(empty, line, start, code_start, length) { } -location_t::location_t(const std::string &filename, std::size_t line, std::size_t start, std::size_t code_start, std::size_t length): filename(filename) { +location_t::location_t(const std::string &filename, std::size_t line, std::size_t start, std::size_t code_start, std::size_t length): + filename(filename) { this->length = length; this->code_start = code_start; this->line = line; this->start = start; } -const location_t location_t::NONE = { }; +const location_t location_t::NONE = {}; diff --git a/src/utils/message.cc b/src/utils/message.cc index 61959ea..a65754c 100644 --- a/src/utils/message.cc +++ b/src/utils/message.cc @@ -1,6 +1,6 @@ +#include "utils/message.hh" #include #include -#include "utils/message.hh" using namespace ppc; @@ -10,15 +10,27 @@ namespace ppc::messages { std::string level_readable; switch (level) { - case message_t::DEBUG: level_readable = "debug"; break; - case message_t::SUGGESTION: level_readable = "suggestion"; break; - case message_t::INFO: level_readable = "info"; break; - case message_t::WARNING: level_readable = "warning"; break; - case message_t::ERROR: level_readable = "error"; break; - default: level_readable = "what?"; break; + case message_t::DEBUG: + level_readable = "debug"; + break; + case message_t::SUGGESTION: + level_readable = "suggestion"; + break; + case message_t::INFO: + level_readable = "info"; + break; + case message_t::WARNING: + level_readable = "warning"; + break; + case message_t::ERROR: + level_readable = "error"; + break; + default: + level_readable = "what?"; + break; } - std::stringstream res { }; + std::stringstream res {}; if (loc_readable.length()) res << loc_readable << ": "; res << level_readable << ": " << content; @@ -42,7 +54,7 @@ namespace ppc::messages { if (msg.level < threshold) continue; std::string loc_readable = msg.location.to_string(); - + switch (msg.level) { case message_t::DEBUG: output << (color_output ? "\e[38;5;8mdebug: " : "debug: "); @@ -51,7 +63,7 @@ namespace ppc::messages { output << (color_output ? "\e[38;5;45msuggestion: " : "suggestion: "); break; case message_t::INFO: - output << (color_output ? "\e[38;5;33minfo: ": "info: "); + output << (color_output ? "\e[38;5;33minfo: " : "info: "); break; case message_t::WARNING: output << (color_output ? "\e[38;5;214mwarning: " : "warning: "); diff --git a/src/utils/strings.cc b/src/utils/strings.cc index 1482a81..44ce163 100644 --- a/src/utils/strings.cc +++ b/src/utils/strings.cc @@ -1,5 +1,5 @@ -#include #include "utils/strings.hh" +#include using namespace ppc; @@ -11,10 +11,10 @@ std::vector str::split(const std::string &splittable, std::initiali if (std::string { splitters }.find(c) == std::string::npos) { buff << c; } - else { + else { if (!buff.str().empty() || !remove_empty_entries) { res.push_back(buff.str()); - buff = { }; + buff = {}; } } } diff --git a/src/utils/threading.cc b/src/utils/threading.cc index 04ea928..281aef3 100644 --- a/src/utils/threading.cc +++ b/src/utils/threading.cc @@ -10,7 +10,7 @@ using namespace std::string_literals; threading::thread_t threading::thread_t::start_impl(void *func, void *args) { DWORD id; - HANDLE hnd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, args, 0, &id); + HANDLE hnd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, args, 0, &id); if (!hnd) throw "Couldn't create thread."s; return { hnd }; @@ -31,14 +31,14 @@ threading::thread_t::~thread_t() { threading::thread_t threading::thread_t::start_impl(void *func, void *args) { pthread_t *handle = new pthread_t; - pthread_create(handle, nullptr, (void* (*)(void *))func, args); + pthread_create(handle, nullptr, (void *(*) (void *) ) func, args); return { handle }; } int threading::thread_t::join() const { - return pthread_join(*(pthread_t*)handle, nullptr); + return pthread_join(*(pthread_t *) handle, nullptr); } threading::thread_t::~thread_t() { - delete (pthread_t*)handle; + delete (pthread_t *) handle; } #endif \ No newline at end of file From f370824cd8231cf1a467cc963436f24c025c33fa Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 20 Jan 2023 16:46:11 +0200 Subject: [PATCH 02/14] chore: add .clang-format --- .clang-format | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 3 ++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f22054c --- /dev/null +++ b/.clang-format @@ -0,0 +1,70 @@ +Language: Cpp +BasedOnStyle: Google +IndentWidth: 4 +UseTab: Never +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +BreakBeforeClosingBracket: true +ColumnLimit: 0 +MaxEmptyLinesToKeep: 2 + +EmptyLineBeforeAccessModifier: Never + +BinPackArguments: true +BinPackParameters: true + +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeTry: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false + +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: true +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: AllIfsAndElse +AllowShortLoopsOnASingleLine: false + +BreakBeforeComma: true +AlignConsecutiveAssignments: false +AlignAfterOpenBracket: BlockIndent +Cpp11BracedListStyle: false +SpaceBeforeCpp11BracedList: true + +BitFieldColonSpacing: After +BreakConstructorInitializers: AfterColon +BreakInheritanceListStyle: AfterColon +SpaceBeforeCtorInitializerColon: false +SpaceBeforeInheritanceColon: false + +SpaceInEmptyBlock: true + +IncludeBlocks: Merge + +IncludeCategories: +- Regex: '^<' + Priority: 0 + SortPriority: 0 +- Regex: '^"' + Priority: -1 + SortPriority: 0 + +FixNamespaceComments: false +NamespaceIndentation: All + +SpaceAfterCStyleCast: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 051d50f..0e936b5 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ !CONTRIBUTING.md !Makefile !README.md -!.gitignore \ No newline at end of file +!.gitignore +!.clang-format \ No newline at end of file From 0a3e65a24b8da4d9b5d5ebb7dd3f238ff633cdab Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Mon, 23 Jan 2023 00:54:52 +0200 Subject: [PATCH 03/14] fix: fuck clang format --- .clang-format | 70 --------------------------------------------------- 1 file changed, 70 deletions(-) delete mode 100644 .clang-format diff --git a/.clang-format b/.clang-format deleted file mode 100644 index f22054c..0000000 --- a/.clang-format +++ /dev/null @@ -1,70 +0,0 @@ -Language: Cpp -BasedOnStyle: Google -IndentWidth: 4 -UseTab: Never -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: true -BreakBeforeClosingBracket: true -ColumnLimit: 0 -MaxEmptyLinesToKeep: 2 - -EmptyLineBeforeAccessModifier: Never - -BinPackArguments: true -BinPackParameters: true - -BreakBeforeBraces: Custom -BraceWrapping: - AfterCaseLabel: false - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - AfterExternBlock: false - BeforeTry: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false - -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: true -AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: AllIfsAndElse -AllowShortLoopsOnASingleLine: false - -BreakBeforeComma: true -AlignConsecutiveAssignments: false -AlignAfterOpenBracket: BlockIndent -Cpp11BracedListStyle: false -SpaceBeforeCpp11BracedList: true - -BitFieldColonSpacing: After -BreakConstructorInitializers: AfterColon -BreakInheritanceListStyle: AfterColon -SpaceBeforeCtorInitializerColon: false -SpaceBeforeInheritanceColon: false - -SpaceInEmptyBlock: true - -IncludeBlocks: Merge - -IncludeCategories: -- Regex: '^<' - Priority: 0 - SortPriority: 0 -- Regex: '^"' - Priority: -1 - SortPriority: 0 - -FixNamespaceComments: false -NamespaceIndentation: All - -SpaceAfterCStyleCast: true \ No newline at end of file From c8043fab9a58e37162aaeb1aeb4364be9c5d3b0f Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Mon, 23 Jan 2023 01:12:46 +0200 Subject: [PATCH 04/14] chore: major recoding, imports and namespaces --- include/compiler.hh | 2 +- include/compiler/treeifier.hh | 11 - include/compiler/treeifier/ast.hh | 105 ----- include/lang/common.hh | 6 +- include/treeifier/constr.hh | 94 +++++ include/treeifier/constr/glob.hh | 9 + .../ast => treeifier/constr}/helper.hh | 41 +- include/treeifier/constr/identifier.hh | 8 + include/treeifier/constr/nmsp.hh | 9 + include/{compiler => }/treeifier/lexer.hh | 2 +- include/{compiler => }/treeifier/tokenizer.hh | 4 +- include/utils/data.hh | 2 +- src/compiler/treeifier/ast/ast.cc | 35 -- src/compiler/treeifier/ast/conv.cc | 70 ---- src/compiler/treeifier/ast/parsers/exp.cc | 364 ------------------ src/compiler/treeifier/ast/parsers/export.cc | 16 - src/compiler/treeifier/ast/parsers/field.cc | 38 -- src/compiler/treeifier/ast/parsers/func.cc | 92 ----- src/compiler/treeifier/ast/parsers/glob.cc | 68 ---- src/compiler/treeifier/ast/parsers/group.cc | 90 ----- .../treeifier/ast/parsers/identifier.cc | 15 - src/compiler/treeifier/ast/parsers/nmsp.cc | 21 - src/compiler/treeifier/ast/parsers/stat.cc | 98 ----- src/compiler/treeifier/ast/parsers/struct.cc | 24 -- src/compiler/treeifier/ast/parsers/type.cc | 35 -- src/main.proj | 2 +- src/main/main.cc | 174 +++++---- src/{compiler.proj => treeifier.proj} | 2 +- src/treeifier/ast.cc | 36 ++ src/treeifier/constr/glob.cc | 41 ++ src/treeifier/constr/identifier.cc | 16 + src/treeifier/constr/nmsp.cc | 26 ++ src/{compiler => }/treeifier/lexer.cc | 4 +- src/{compiler => }/treeifier/operators.cc | 6 +- src/{compiler => }/treeifier/tokenizer.cc | 6 +- 35 files changed, 355 insertions(+), 1217 deletions(-) delete mode 100644 include/compiler/treeifier.hh delete mode 100644 include/compiler/treeifier/ast.hh create mode 100644 include/treeifier/constr.hh create mode 100644 include/treeifier/constr/glob.hh rename include/{compiler/treeifier/ast => treeifier/constr}/helper.hh (73%) create mode 100644 include/treeifier/constr/identifier.hh create mode 100644 include/treeifier/constr/nmsp.hh rename include/{compiler => }/treeifier/lexer.hh (95%) rename include/{compiler => }/treeifier/tokenizer.hh (95%) delete mode 100644 src/compiler/treeifier/ast/ast.cc delete mode 100644 src/compiler/treeifier/ast/conv.cc delete mode 100644 src/compiler/treeifier/ast/parsers/exp.cc delete mode 100644 src/compiler/treeifier/ast/parsers/export.cc delete mode 100644 src/compiler/treeifier/ast/parsers/field.cc delete mode 100644 src/compiler/treeifier/ast/parsers/func.cc delete mode 100644 src/compiler/treeifier/ast/parsers/glob.cc delete mode 100644 src/compiler/treeifier/ast/parsers/group.cc delete mode 100644 src/compiler/treeifier/ast/parsers/identifier.cc delete mode 100644 src/compiler/treeifier/ast/parsers/nmsp.cc delete mode 100644 src/compiler/treeifier/ast/parsers/stat.cc delete mode 100644 src/compiler/treeifier/ast/parsers/struct.cc delete mode 100644 src/compiler/treeifier/ast/parsers/type.cc rename src/{compiler.proj => treeifier.proj} (52%) create mode 100644 src/treeifier/ast.cc create mode 100644 src/treeifier/constr/glob.cc create mode 100644 src/treeifier/constr/identifier.cc create mode 100644 src/treeifier/constr/nmsp.cc rename src/{compiler => }/treeifier/lexer.cc (98%) rename src/{compiler => }/treeifier/operators.cc (89%) rename src/{compiler => }/treeifier/tokenizer.cc (98%) diff --git a/include/compiler.hh b/include/compiler.hh index a1c6d0c..133323b 100644 --- a/include/compiler.hh +++ b/include/compiler.hh @@ -1,6 +1,6 @@ #ifndef PPC_COMPILER_H #define PPC_COMPILER_H 1 -#include "compiler/treeifier.hh" +#include "treeifier.hh" #endif \ No newline at end of file diff --git a/include/compiler/treeifier.hh b/include/compiler/treeifier.hh deleted file mode 100644 index c4b4d44..0000000 --- a/include/compiler/treeifier.hh +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef PPC_TREEIFIER_H -#define PPC_TREEIFIER_H 1 - -#include "utils/message.hh" - -namespace ppc::compiler { - // bool treeify(ppc::messages::msg_stack_t &msg_stack, const std::string &filename, const std::string &source, namespace_t *pout); - // bool treeify_file(const std::string &filename, ppc::messages::msg_stack_t &pmsg_stack, namespace_t *pout); -} - -#endif \ No newline at end of file diff --git a/include/compiler/treeifier/ast.hh b/include/compiler/treeifier/ast.hh deleted file mode 100644 index e998f67..0000000 --- a/include/compiler/treeifier/ast.hh +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "compiler/treeifier/tokenizer.hh" -#include "lang/common.hh" -#include "utils/data.hh" - -using namespace std::string_literals; -using namespace ppc; -using namespace ppc::lang; -using namespace ppc::messages; - -namespace ppc::comp::tree::ast { - struct ast_ctx_t; - using parser_func_t = bool(ast_ctx_t &ctx, size_t &res_i, data::map_t &out); - using parser_t = parser_func_t *; - - class group_t { - private: - std::map named_parsers; - std::set unnamed_parsers; - std::map parsers; - public: - group_t &replace(const std::string &name, parser_t parser); - 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; - }; - - struct ast_ctx_t { - private: - std::unordered_map groups; - public: - msg_stack_t &messages; - std::vector &tokens; - std::set imports; - loc_namespace_name_t nmsp; - - ast_ctx_t &operator=(const ast_ctx_t &other) = delete; - - template - bool parse(const T &parser, size_t &i, data::map_t &out) { - return parser(*this, i, out); - } - - group_t &group(const std::string &name); - - template - static data::map_t parse(const T &glob, msg_stack_t &messages, std::vector &tokens) { - ast_ctx_t ctx(messages, tokens); - data::map_t res; - size_t i = 0; - - if (!ctx.parse(glob, i, res)) throw message_t::error("Failed to compile."); - return res; - } - - ast_ctx_t(msg_stack_t &messages, std::vector &tokens); - }; - - namespace conv { - data::map_t identifier_to_map(const located_t &loc); - located_t map_to_identifier(const data::map_t &map); - - data::string_t loc_to_map(const location_t &loc); - location_t map_to_loc(const data::string_t &map); - - data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp); - loc_namespace_name_t map_to_nmsp(const data::map_t &map); - } // namespace conv - - class construct_t { - public: - virtual const std::string &name() const = 0; - }; - - class parser_t { - public: - virtual bool parse(ast_ctx_t &ctx, size_t &res_i, construct_t *&out) const = 0; - virtual bool simplify(ast_ctx_t &ctx, size_t &res_i, const construct_t *global, const construct_t *container, const construct_t *current) const = 0; - }; - - namespace constr { - class glob_con_t: public construct_t { - const std::string &name() const { return "$_glob"s; } - bool parse(ast_ctx_t &ctx, size_t &res_i, construct_t *&out) const; - }; - } - - namespace parsers { - - } - - 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, 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/lang/common.hh b/include/lang/common.hh index ef7178a..ba966b9 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -4,7 +4,7 @@ #include namespace ppc::lang { - struct namespace_name_t : public std::vector { + struct namespace_name_t: public std::vector { using base = std::vector; int compare(const namespace_name_t &other) const; @@ -42,7 +42,7 @@ struct std::hash { namespace ppc::lang { template - struct located_t : T { + struct located_t: T { location_t location; located_t(location_t loc, const T &val): T(val), location(loc) { } @@ -66,7 +66,7 @@ namespace ppc::lang { slocated_t() { } }; - struct loc_namespace_name_t : public std::vector> { + struct loc_namespace_name_t: public std::vector> { using base = std::vector>; int compare(const loc_namespace_name_t &other) const; diff --git a/include/treeifier/constr.hh b/include/treeifier/constr.hh new file mode 100644 index 0000000..cd8d39a --- /dev/null +++ b/include/treeifier/constr.hh @@ -0,0 +1,94 @@ +#pragma once + +#include "lang/common.hh" +#include "treeifier/tokenizer.hh" +#include "utils/data.hh" +#include +#include +#include +#include +#include +#include +#include + +using namespace std::string_literals; +using namespace ppc; +using namespace ppc::lang; +using namespace ppc::messages; + +namespace ppc::tree::constr { + struct ast_ctx_t; + + struct glob_t { + loc_namespace_name_t nmsp; + std::vector imports; + }; + + template + class parser_t { + public: + virtual bool operator()(ast_ctx_t &ctx, size_t &res_i, T &out) const = 0; + virtual bool simplify(ast_ctx_t &ctx, GlobT &glob, T &val) const = 0; +#ifdef PROFILE_debug + virtual void print(const T &val) { + std::cout << "(unknown)"; + } +#endif + }; + + + struct ast_ctx_t { + public: + msg_stack_t &messages; + std::vector &tokens; + loc_namespace_name_t nmsp; + + ast_ctx_t &operator=(const ast_ctx_t &other) = delete; + + template + bool parse(const parser_t &parser, size_t &i, T &out) { + return parser(*this, i, out); + } + + template + static T parse(const parser_t &glob, msg_stack_t &messages, std::vector &tokens) { + ast_ctx_t ctx(messages, tokens); + T res; + size_t i = 0; + + if (!ctx.parse(glob, i, res)) throw message_t::error("Failed to compile."); + return res; + } + + ast_ctx_t(msg_stack_t &messages, std::vector &tokens); + }; + + template + class inspoint_t { + private: + std::map named_parsers; + std::set unnamed_parsers; + std::map parsers; + public: + inspoint_t &replace(const std::string &name, const T &parser) { + auto it = parsers.find(name); + + if (parsers.find(name) == parsers.end()) { + throw "The parser '" + name + "' isn't in the group."; + } + + it->second = parser; + + return *this; + } + inspoint_t &add(const std::string &name, const T &parser); + inspoint_t &add(const std::string &name, const lang::namespace_name_t &identifier, const T &parser); + + bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const; + }; + + // 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, 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/treeifier/constr/glob.hh b/include/treeifier/constr/glob.hh new file mode 100644 index 0000000..9303979 --- /dev/null +++ b/include/treeifier/constr/glob.hh @@ -0,0 +1,9 @@ +#include "treeifier/constr.hh" + +namespace ppc::tree::constr { + class glob_parser_t: public parser_t { + public: + bool operator()(ast_ctx_t &ctx, size_t &res_i, glob_t &out) const override; + bool simplify(ast_ctx_t &ctx, glob_t &glob, glob_t &val) const override { return false; } + }; +} \ No newline at end of file diff --git a/include/compiler/treeifier/ast/helper.hh b/include/treeifier/constr/helper.hh similarity index 73% rename from include/compiler/treeifier/ast/helper.hh rename to include/treeifier/constr/helper.hh index 971c562..c91f3a9 100644 --- a/include/compiler/treeifier/ast/helper.hh +++ b/include/treeifier/constr/helper.hh @@ -1,13 +1,13 @@ -#include "compiler/treeifier/ast.hh" +#include "treeifier/constr.hh" using namespace ppc; using namespace ppc::lang; using namespace ppc::data; -using namespace ppc::comp::tree; -using namespace ppc::comp::tree::ast; +using namespace ppc::tree; +using namespace ppc::tree::constr; -namespace ppc::comp::tree::ast { - struct tree_helper_t { +namespace ppc::tree::constr { + struct parse_helper_t { private: ast_ctx_t &ctx; size_t &res_i; @@ -105,37 +105,12 @@ namespace ppc::comp::tree::ast { } template - bool push_parse(const T &parser, data::array_t &out) { - data::map_t res; - if (parse(parser, res)) { - out.push_back(res); - return true; - } - else return false; - } - - template - bool parse(const T &parser, data::map_t &out) { + bool parse(const parser_t &parser, T &out) { return ctx.parse(parser, i, out); } template - void force_push_parse(const T &parser, std::string message, data::array_t &out) { - throw_ended(message); - bool success; - - try { - success = push_parse(parser, out); - } - catch (const message_t &msg) { - ctx.messages.push(msg); - success = false; - } - - if (!success) err(message); - } - template - void force_parse(const T &parser, std::string message, data::map_t &out) { + void force_parse(const parser_t &parser, std::string message, T &out) { throw_ended(message); bool success; @@ -150,7 +125,7 @@ namespace ppc::comp::tree::ast { if (!success) err(message); } - tree_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { + parse_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { this->i = i; } }; diff --git a/include/treeifier/constr/identifier.hh b/include/treeifier/constr/identifier.hh new file mode 100644 index 0000000..b16e615 --- /dev/null +++ b/include/treeifier/constr/identifier.hh @@ -0,0 +1,8 @@ +#include "treeifier/constr.hh" + +namespace ppc::tree::constr { + struct identifier_parser_t: public parser_t> { + bool operator()(ast_ctx_t &ctx, size_t &res_i, located_t &out) const override; + bool simplify(ast_ctx_t &ctx, glob_t &glob, located_t &val) const override { return false; } + }; +} \ No newline at end of file diff --git a/include/treeifier/constr/nmsp.hh b/include/treeifier/constr/nmsp.hh new file mode 100644 index 0000000..0c10a85 --- /dev/null +++ b/include/treeifier/constr/nmsp.hh @@ -0,0 +1,9 @@ +#include "treeifier/constr/identifier.hh" +#include "treeifier/constr.hh" + +namespace ppc::tree::constr { + struct nmsp_parser_t: public parser_t { + bool operator()(ast_ctx_t &ctx, size_t &res_i, loc_namespace_name_t &out) const override; + bool simplify(ast_ctx_t &ctx, glob_t &glob, loc_namespace_name_t &val) const override { return false; } + }; +} \ No newline at end of file diff --git a/include/compiler/treeifier/lexer.hh b/include/treeifier/lexer.hh similarity index 95% rename from include/compiler/treeifier/lexer.hh rename to include/treeifier/lexer.hh index b36d9f8..c42090b 100644 --- a/include/compiler/treeifier/lexer.hh +++ b/include/treeifier/lexer.hh @@ -3,7 +3,7 @@ #include "utils/location.hh" #include "utils/message.hh" -namespace ppc::comp::tree::lex { +namespace ppc::tree::lex { struct token_t { enum kind_t { NONE, diff --git a/include/compiler/treeifier/tokenizer.hh b/include/treeifier/tokenizer.hh similarity index 95% rename from include/compiler/treeifier/tokenizer.hh rename to include/treeifier/tokenizer.hh index c8e2034..e60db90 100644 --- a/include/compiler/treeifier/tokenizer.hh +++ b/include/treeifier/tokenizer.hh @@ -2,9 +2,9 @@ #include "utils/location.hh" #include "utils/message.hh" -#include "compiler/treeifier/lexer.hh" +#include "treeifier/lexer.hh" -namespace ppc::comp::tree { +namespace ppc::tree { enum operator_t { NONE, diff --git a/include/utils/data.hh b/include/utils/data.hh index a4e8b4e..6353d80 100644 --- a/include/utils/data.hh +++ b/include/utils/data.hh @@ -116,5 +116,5 @@ namespace ppc::data { } }; - class array_t : public std::vector { }; + class array_t: public std::vector { }; } \ No newline at end of file diff --git a/src/compiler/treeifier/ast/ast.cc b/src/compiler/treeifier/ast/ast.cc deleted file mode 100644 index e875f59..0000000 --- a/src/compiler/treeifier/ast/ast.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "compiler/treeifier/ast.hh" - -using namespace ppc; -using namespace ppc::data; -using namespace ppc::lang; -using namespace ppc::comp::tree::ast; - -group_t &ast_ctx_t::group(const std::string &name) { - if (groups.find(name) == groups.end()) return groups[name] = {}; - else return groups[name]; -} - -ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): - messages(messages), tokens(tokens) { - group("$_exp_val") - .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("$_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("$_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/conv.cc b/src/compiler/treeifier/ast/conv.cc deleted file mode 100644 index 41fd248..0000000 --- a/src/compiler/treeifier/ast/conv.cc +++ /dev/null @@ -1,70 +0,0 @@ -#include "compiler/treeifier/ast.hh" -#include - -namespace ppc::comp::tree::ast::conv { - data::map_t identifier_to_map(const located_t &loc) { - return { - { "location", conv::loc_to_map(loc.location) }, - { "content", loc }, - { "$_name", "$_identifier" }, - }; - } - located_t map_to_identifier(const data::map_t &map) { - return { conv::map_to_loc(map["location"].string()), map["content"].string() }; - } - - data::string_t loc_to_map(const location_t &loc) { - std::stringstream res; - res << loc.filename << ':' << loc.line + 1 << ':' << loc.start + 1 << ':' << loc.code_start + 1 << ':' << loc.length + 1; - return res.str(); - } - location_t map_to_loc(const data::string_t &map) { - std::stringstream res; - res.str(map); - - std::string filename; - std::string line; - std::string start; - std::string code_start; - std::string length; - - std::getline(res, filename, ':'); - std::getline(res, line, ':'); - std::getline(res, start, ':'); - std::getline(res, code_start, ':'); - std::getline(res, length, ':'); - - return { filename, std::stoull(line) - 1, std::stoull(start) - 1, std::stoull(code_start) - 1, std::stoull(length) - 1 }; - } - - data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp) { - data::map_t res; - - auto arr = res["content"].array({}); - - for (const auto &segment : nmsp) { - arr.push_back({ - { "location", loc_to_map(segment.location) }, - { "content", segment }, - { "$_name", "$_nmsp" }, - }); - } - - return res; - } - loc_namespace_name_t map_to_nmsp(const data::map_t &map) { - loc_namespace_name_t res; - - for (const auto &segment : map["content"].array()) { - try { - auto val = map_to_identifier(segment.map()); - res.push_back(val); - } - catch (const message_t &) { - throw "'content' of a namespace map must contain only identifiers."; - } - } - - return res; - } -} diff --git a/src/compiler/treeifier/ast/parsers/exp.cc b/src/compiler/treeifier/ast/parsers/exp.cc deleted file mode 100644 index 929d85a..0000000 --- a/src/compiler/treeifier/ast/parsers/exp.cc +++ /dev/null @@ -1,364 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" -#include -#include - -enum precedence_t { - NONE, - POSTFIX, - PREFIX, - MULT, - ADD, - SHIFT, - COMP, - EQU, - BIN_AND, - BIN_XOR, - BIN_OR, - BOOL_AND, - BOOL_OR, - TERNARY, - ASSIGN, - PAREN, - CALL_START, -}; - -struct op_data_t { - precedence_t precedence; - size_t op_n; - std::string name; - bool assoc; -}; - -op_data_t sizeof_data { precedence_t::PREFIX, 1, "sizeof", true }; - -std::map pre_ops { - { operator_t::INCREASE, { precedence_t::PREFIX, 1, "inc_pre" } }, - { operator_t::DECREASE, { precedence_t::PREFIX, 1, "dec_pre" } }, - { operator_t::ADD, { precedence_t::PREFIX, 1, "positive" } }, - { operator_t::SUBTRACT, { precedence_t::PREFIX, 1, "negative" } }, - { operator_t::BITWISE_NEGATIVE, { precedence_t::PREFIX, 1, "flip" } }, - { operator_t::MULTIPLY, { precedence_t::PREFIX, 1, "dereference" } }, - { operator_t::AND, { precedence_t::PREFIX, 1, "reference" } }, -}; -std::map bin_ops { - { operator_t::INCREASE, { precedence_t::POSTFIX, 1, "inc_post" } }, - { operator_t::DECREASE, { precedence_t::POSTFIX, 1, "dec_post" } }, - { (operator_t)-1, sizeof_data }, - - { operator_t::ADD, { precedence_t::ADD, 2, "add" } }, - { operator_t::SUBTRACT, { precedence_t::ADD, 2, "subtract" } }, - - { operator_t::MULTIPLY, { precedence_t::MULT, 2, "multiply" } }, - { operator_t::DIVIDE, { precedence_t::MULT, 2, "divide" } }, - { operator_t::MODULO, { precedence_t::MULT, 2, "modulo" } }, - - { operator_t::SHIFT_LEFT, { precedence_t::SHIFT, 2, "shl" } }, - { operator_t::SHIFT_RIGHT, { precedence_t::SHIFT, 2, "shr" } }, - - { operator_t::LESS_THAN, { precedence_t::COMP, 2, "less" } }, - { operator_t::LESS_THAN_EQUALS, { precedence_t::COMP, 2, "less_eq" } }, - { operator_t::GREATER_THAN, { precedence_t::COMP, 2, "great" } }, - { operator_t::GREATER_THAN_EQUALS, { precedence_t::COMP, 2, "great_eq" } }, - - { operator_t::EQUALS, { precedence_t::EQU, 2, "eq" } }, - { operator_t::NOT_EQUALS, { precedence_t::EQU, 2, "neq" } }, - - { operator_t::AND, { precedence_t::BIN_AND, 2, "great_eq" } }, - { operator_t::OR, { precedence_t::BIN_OR, 2, "great_eq" } }, - { operator_t::XOR, { precedence_t::BIN_XOR, 2, "great_eq" } }, - - { operator_t::DOUBLE_AND, { precedence_t::BOOL_AND, 2, "great_eq" } }, - { operator_t::DOUBLE_OR, { precedence_t::BOOL_OR, 2, "great_eq" } }, - - { operator_t::ASSIGN, { precedence_t::ASSIGN, 2, "assign", true } }, - { operator_t::ASSIGN_ADD, { precedence_t::ASSIGN, 2, "assign_add", true } }, - { operator_t::ASSIGN_SUBTRACT, { precedence_t::ASSIGN, 2, "assign_subtract", true } }, - { operator_t::ASSIGN_MULTIPLY, { precedence_t::ASSIGN, 2, "assign_multiply", true } }, - { operator_t::ASSIGN_DIVIDE, { precedence_t::ASSIGN, 2, "assign_divide", true } }, - { operator_t::ASSIGN_MODULO, { precedence_t::ASSIGN, 2, "assign_modulo", true } }, - { operator_t::ASSIGN_SHIFT_LEFT, { precedence_t::ASSIGN, 2, "assign_shl", true } }, - { operator_t::ASSIGN_SHIFT_RIGHT, { precedence_t::ASSIGN, 2, "assign_shr", true } }, - { operator_t::ASSIGN_XOR, { precedence_t::ASSIGN, 2, "assign_xor", true } }, - { operator_t::ASSIGN_AND, { precedence_t::ASSIGN, 2, "assign_and", true } }, - { operator_t::ASSIGN_OR, { precedence_t::ASSIGN, 2, "assign_or", true } }, - { operator_t::ASSIGN_DOUBLE_AND, { precedence_t::ASSIGN, 2, "assign_dand", true } }, - { operator_t::ASSIGN_DOUBLE_OR, { precedence_t::ASSIGN, 2, "assign_dor", true } }, - { operator_t::ASSIGN_NULL_COALESCING, { precedence_t::ASSIGN, 2, "assign_null_coal", true } }, -}; - -map_t op_to_map(located_t op) { - return { - { "$_name", "$_operator" }, - { "ops", array_t() }, - { "location", conv::loc_to_map(op.location) }, - { "op", op.name }, - }; -} - -bool pop(std::vector> &op_stack, array_t &res) { - if (op_stack.empty()) return false; - - auto map = op_to_map(op_stack.back()); - auto op_n = op_stack.back().op_n; - auto loc = op_stack.back().location; - op_stack.pop_back(); - - if (res.size() < op_n) return false; - - auto &ops = map["ops"].array(); - - - for (size_t i = 0; i < op_n; i++) { - ops.push_back(res.back()); - loc = loc.intersect(conv::map_to_loc(res.back().map()["location"].string())); - res.pop_back(); - } - - map["location"] = conv::loc_to_map(loc); - - std::reverse(ops.begin(), ops.end()); - res.push_back(map); - - return true; -} -bool pop_paren(std::vector> &op_stack, array_t &res) { - bool has_paren = false; - for (const auto &op : op_stack) { - if (op.precedence == precedence_t::PAREN) { - has_paren = true; - break; - } - } - if (!has_paren) return false; - - while (true) { - if (op_stack.back().precedence == precedence_t::PAREN) break; - if (!pop(op_stack, res)) return false; - } - - op_stack.pop_back(); - return true; -} -bool pop_call(size_t n, location_t loc, std::vector> &op_stack, array_t &res) { - map_t call = { - { "$_name", "$_call" }, - }; - - array_t &args = call["args"].array({}); - - while (true) { - if (op_stack.back().precedence == precedence_t::CALL_START) break; - if (!pop(op_stack, res)) return false; - } - loc = loc.intersect(op_stack.back().location); - op_stack.pop_back(); - call["location"] = conv::loc_to_map(loc); - - for (size_t i = 0; i < n; i++) { - args.push_back(res.back()); - res.pop_back(); - } - - std::reverse(args.begin(), args.end()); - - call["func"] = res.back(); - res.pop_back(); - res.push_back(call); - - return true; -} -bool pop_until(const op_data_t &data, tree_helper_t &h, std::vector> &op_stack, array_t &res) { - while (!op_stack.empty()) { - auto &back_data = op_stack.back(); - if (data.assoc ? back_data.precedence >= data.precedence : back_data.precedence > data.precedence) break; - - if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator."); - } - return true; -} - -bool ast::parse_exp_var(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - return ctx.parse(parse_nmsp, res_i, out); -} -bool ast::parse_exp_int_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - if (h.curr().is_int_literal()) { - auto &arr = out["content"].array({}); - for (auto b : h.curr().literal()) { - arr.push_back((float)b); - } - out["location"] = conv::loc_to_map(h.loc()); - return h.submit(true); - } - - return false; -} -bool ast::parse_exp_str_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - if (h.curr().is_str_literal()) { - auto &arr = out["content"].array({}); - for (auto b : h.curr().literal()) { - arr.push_back((float)b); - } - out["location"] = conv::loc_to_map(h.loc()); - return h.submit(true); - } - - return false; -} - -bool ast::parse_exp(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - bool last_val = false; - map_t val; - std::vector> op_stack; - std::vector call_args_n; - auto res = array_t(); - - - while (true) { - if (h.ended()) break; - - if (!last_val && h.curr().is_identifier("sizeof")) { - op_stack.push_back({ h.loc(), sizeof_data }); - h.advance("Expected a value on the right side of the operator."); - continue; - } - if (!last_val && h.push_parse(ctx.group("$_exp_val"), res)) { - last_val = true; - continue; - } - if (h.curr().is_operator()) { - auto op = h.curr()._operator(); - if (last_val) { - if (op == operator_t::PAREN_OPEN) { - h.advance("Expected an argument or closing parens."); - op_stack.push_back({ h.loc(), { precedence_t::CALL_START } }); - if (h.curr().is_operator(operator_t::PAREN_CLOSE)) { - pop_call(0, h.loc(), op_stack, res); - } - else { - call_args_n.push_back(1); - } - last_val = false; - } - else if (op == operator_t::PAREN_CLOSE) { - bool is_call = false, is_paren = false; - - for (auto i = op_stack.rbegin(); i != op_stack.rend(); i++) { - if (i->precedence == precedence_t::PAREN) { - is_paren = true; - break; - } - else if (i->precedence == precedence_t::CALL_START) { - is_call = true; - break; - } - } - - if (is_call) { - pop_call(call_args_n.back(), h.loc(), op_stack, res); - call_args_n.pop_back(); - } - else if (is_paren) pop_paren(op_stack, res); - else break; - - if (!h.try_advance()) break; - } - else if (op == operator_t::COMMA) { - if (call_args_n.size() == 0) break; - h.advance("Expected an argument."); - - pop_until({ .precedence = precedence_t::CALL_START, .assoc = true }, h, op_stack, res); - call_args_n.back()++; - last_val = false; - } - else if (op == operator_t::COLON) { - h.advance("Expected a type."); - pop_until({ .precedence = precedence_t::PREFIX, .assoc = true }, h, op_stack, res); - map_t cast = { - { "$_name", "$_cast" }, - { "exp", res.back() }, - }; - - res.pop_back(); - h.force_parse(parse_type, "Expected a type.", cast["type"].map({})); - cast["location"] = conv::loc_to_map(location_t::intersect( - conv::map_to_loc(cast["exp"].map()["location"].string()), - conv::map_to_loc(cast["type"].map()["location"].string()) - )); - res.push_back(cast); - } - else if (op == operator_t::DOT || op == operator_t::PTR_MEMBER) { - h.advance("Expected an identifier."); - pop_until({ .precedence = precedence_t::POSTFIX, .assoc = true }, h, op_stack, res); - - map_t member_access = { - { "exp", res.back() }, - { "is_ptr", op == operator_t::PTR_MEMBER }, - }; - h.force_parse(parse_identifier, "Expected an identifier.", member_access["name"].map({})); - member_access["location"] = conv::loc_to_map( - conv::map_to_loc(member_access["name"].map()["location"].string()) - .intersect(conv::map_to_loc(res.back().map()["location"].string())) - ); - res.pop_back(); - res.push_back(member_access); - } - else if (bin_ops.find(op) != bin_ops.end()) { - auto data = bin_ops[op]; - pop_until(data, h, op_stack, res); - op_stack.push_back({ h.loc(), data }); - - if (data.op_n == 1) { - last_val = true; - if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator."); - if (h.try_advance()) break; - } - else { - last_val = false; - h.advance("Expected a value on the right side of the operator."); - } - } - else break; - } - else { - if (op == operator_t::PAREN_OPEN) { - op_stack.push_back({ h.loc(), { precedence_t::PAREN } }); - h.advance("Expected a value."); - last_val = false; - } - else if (pre_ops.find(op) != pre_ops.end()) { - op_stack.push_back({ h.loc(), pre_ops[op] }); - h.advance("Expected a value on the right side of the operator."); - } - else break; - } - continue; - } - else break; - } - - if (res.size() == 0) return false; - - while (!op_stack.empty()) { - if (op_stack.back().precedence == precedence_t::PAREN) throw message_t::error("Unclosed paren.", op_stack.back().location); - if (op_stack.back().precedence == precedence_t::CALL_START) throw message_t::error("Unclosed call.", op_stack.back().location); - if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator."); - } - - out = res.front().map(); - - return h.submit(false); -} -bool ast::parse_stat_exp(ast_ctx_t &ctx, size_t &i, map_t &res) { - tree_helper_t h(ctx, i); - if (!h.parse(parse_exp, res)) return false; - if (!h.ended() && 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); -} diff --git a/src/compiler/treeifier/ast/parsers/export.cc b/src/compiler/treeifier/ast/parsers/export.cc deleted file mode 100644 index 1076020..0000000 --- a/src/compiler/treeifier/ast/parsers/export.cc +++ /dev/null @@ -1,16 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" - -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 h.submit(false); -} diff --git a/src/compiler/treeifier/ast/parsers/field.cc b/src/compiler/treeifier/ast/parsers/field.cc deleted file mode 100644 index b2815a5..0000000 --- a/src/compiler/treeifier/ast/parsers/field.cc +++ /dev/null @@ -1,38 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" - -bool ast::parse_field(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - 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; - - h.throw_ended("Expected a colon or an equals sign."); - - if (h.curr().is_operator(operator_t::COLON)) { - h.advance(); - h.force_parse(parse_type, "Expected a type.", out["type"].map({})); - type = true; - } - if (h.curr().is_operator(operator_t::ASSIGN)) { - h.advance(); - h.force_parse(parse_exp, "Expected an expression.", out["value"].map({})); - type = true; - } - - if (!h.ended() && 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); -} diff --git a/src/compiler/treeifier/ast/parsers/func.cc b/src/compiler/treeifier/ast/parsers/func.cc deleted file mode 100644 index e280a36..0000000 --- a/src/compiler/treeifier/ast/parsers/func.cc +++ /dev/null @@ -1,92 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" - -static bool parse_arg(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - 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; - - h.throw_ended("Expected a colon or an equals sign."); - - if (h.curr().is_operator(operator_t::COLON)) { - h.advance(); - h.force_parse(parse_type, "Expected a type.", out["type"].map({})); - type = true; - } - if (h.curr().is_operator(operator_t::ASSIGN)) { - h.advance(); - h.force_parse(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); -} - -bool ast::parse_func(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - 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; - h.advance("Expected a closing paren or a parameter."); - - auto ¶ms = 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(parse_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(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(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(ctx.group("$_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); -} diff --git a/src/compiler/treeifier/ast/parsers/glob.cc b/src/compiler/treeifier/ast/parsers/glob.cc deleted file mode 100644 index a28053f..0000000 --- a/src/compiler/treeifier/ast/parsers/glob.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include "compiler/treeifier/ast.hh" -#include "compiler/treeifier/ast/helper.hh" - -using namespace ppc::comp::tree::ast; - -static bool nmsp_def(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) { - tree_helper_t h(ctx, res_i); - if (h.ended()) return false; - - if (!h.curr().is_identifier("namespace")) return false; - h.advance("Expected a namespace"); - h.force_parse(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))); - return h.submit(false); - } - return h.submit(true); -} -static bool import(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) { - tree_helper_t h(ctx, res_i); - if (h.ended()) return false; - - if (!h.curr().is_identifier("import")) return false; - h.advance("Expected a namespace"); - h.force_parse(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))); - return h.submit(false); - } - - return h.submit(true); -} - -bool ast::parse_glob(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) { - tree_helper_t h(ctx, res_i); - - if (h.ended()) return true; - if (h.parse(nmsp_def, out["namespace"].map({}))) { - ctx.nmsp = conv::map_to_nmsp(out["namespace"].map()); - } - else { - out["namespace"] = data::null; - } - - auto &imports = out["imports"].array({}); - auto &contents = out["content"].array({}); - - while (true) { - map_t map; - if (!h.parse(import, map)) break; - imports.push_back(map); - auto nmsp = conv::map_to_nmsp(map); - - 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(ctx.group("$_def"), contents)) { - ctx.messages.push(message_t::error("Invalid token.", h.loc())); - h.i++; - } - } - - if (!h.ended()) h.err("Invalid token."); - - return h.submit(); -} diff --git a/src/compiler/treeifier/ast/parsers/group.cc b/src/compiler/treeifier/ast/parsers/group.cc deleted file mode 100644 index 410e511..0000000 --- a/src/compiler/treeifier/ast/parsers/group.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include "lang/module.hh" -#include "compiler/treeifier/ast.hh" -#include "compiler/treeifier/tokenizer.hh" -#include "compiler/treeifier/ast/helper.hh" -#include -#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, lang::loc_namespace_name_t &name) { - tree_helper_t h(ctx, i); - map_t res; - if (!h.parse(parse_nmsp, res)) return false; - name = conv::map_to_nmsp(res); - return h.submit(false); -} - - -group_t &group_t::replace(const std::string &name, parser_t parser) { - auto it = parsers.find(name); - - if (parsers.find(name) == parsers.end()) { - throw "The parser '" + name + "' isn't in the group."; - } - - it->second = parser; - - return *this; -} -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."; - } - - parsers.emplace(name, parser); - unnamed_parsers.emplace(name); - - return *this; -} -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."; - } - - parsers.emplace(name, parser); - named_parsers.emplace(identifier, name); - - return *this; -} - -bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { - tree_helper_t h(ctx, i); - - 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_name_map( - named_parsers, names, - 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()); - } - } - - for (auto name : unnamed_parsers) { - out["$_name"] = name; - out.clear(); - if (parsers.at(name)(ctx, i, out)) return true; - } - - stringstream m; - - return false; -} diff --git a/src/compiler/treeifier/ast/parsers/identifier.cc b/src/compiler/treeifier/ast/parsers/identifier.cc deleted file mode 100644 index a1119e0..0000000 --- a/src/compiler/treeifier/ast/parsers/identifier.cc +++ /dev/null @@ -1,15 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" - -bool ast::parse_identifier(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()) { - auto loc = h.loc(); - out["location"] = conv::loc_to_map(loc); - out["content"] = h.curr().identifier(); - return h.submit(); - } - else return false; -} diff --git a/src/compiler/treeifier/ast/parsers/nmsp.cc b/src/compiler/treeifier/ast/parsers/nmsp.cc deleted file mode 100644 index d2cabf5..0000000 --- a/src/compiler/treeifier/ast/parsers/nmsp.cc +++ /dev/null @@ -1,21 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" - -bool ast::parse_nmsp(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - if (h.ended()) return false; - - auto &arr = (out["content"] = array_t()).array(); - - if (!h.push_parse(parse_identifier, arr)) return false; - - while (true) { - if (h.ended()) break; - if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break; - h.advance("Expected an identifier."); - h.force_push_parse(parse_identifier, "Expected an identifier.", arr); - } - - out["location"] = conv::loc_to_map(h.res_loc()); - return h.submit(false); -} diff --git a/src/compiler/treeifier/ast/parsers/stat.cc b/src/compiler/treeifier/ast/parsers/stat.cc deleted file mode 100644 index ff31c03..0000000 --- a/src/compiler/treeifier/ast/parsers/stat.cc +++ /dev/null @@ -1,98 +0,0 @@ -#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("Expected open parens after if keyword."); - 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("Expected open parens after while keyword."); - 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.throw_ended("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 diff --git a/src/compiler/treeifier/ast/parsers/struct.cc b/src/compiler/treeifier/ast/parsers/struct.cc deleted file mode 100644 index 4ab0d94..0000000 --- a/src/compiler/treeifier/ast/parsers/struct.cc +++ /dev/null @@ -1,24 +0,0 @@ -#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/compiler/treeifier/ast/parsers/type.cc b/src/compiler/treeifier/ast/parsers/type.cc deleted file mode 100644 index eebcabf..0000000 --- a/src/compiler/treeifier/ast/parsers/type.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "compiler/treeifier/ast/helper.hh" - -bool ast::parse_type(ast_ctx_t &ctx, size_t &res_i, map_t &out) { - tree_helper_t h(ctx, res_i); - - if (h.ended()) return false; - - auto &nmsp = out["namespace"].map({}); - size_t ptr_n = 0; - - if (!h.parse(parse_nmsp, nmsp)) return false; - - while (!h.ended() && h.curr().is_operator(operator_t::MULTIPLY)) { - ptr_n++; - if (!h.try_advance()) break; - } - - auto &nmsp_arr = nmsp["content"].array(); - - h.i--; - out["location"] = conv::loc_to_map(h.res_loc()); - h.i++; - out["name"] = nmsp_arr.back(); - out["ptr_n"] = (float)ptr_n; - nmsp_arr.pop_back(); - if (nmsp_arr.empty()) out["namespace"] = null; - else { - auto loc_1 = conv::map_to_loc(nmsp_arr.front().map()["location"].string()); - auto loc_2 = conv::map_to_loc(nmsp_arr.back().map()["location"].string()); - auto loc = loc_1.intersect(loc_2); - nmsp["location"] = conv::loc_to_map(loc); - } - - return h.submit(false); -} diff --git a/src/main.proj b/src/main.proj index dd1bfcc..ba8a6bc 100644 --- a/src/main.proj +++ b/src/main.proj @@ -1,2 +1,2 @@ main -utils, compiler \ No newline at end of file +utils, treeifier \ No newline at end of file diff --git a/src/main/main.cc b/src/main/main.cc index 6e9a029..ce28519 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -17,9 +17,10 @@ #endif #include "./opions.hh" -#include "compiler/treeifier/ast.hh" -#include "compiler/treeifier/lexer.hh" -#include "compiler/treeifier/tokenizer.hh" +#include "treeifier/constr.hh" +#include "treeifier/constr/glob.hh" +#include "treeifier/lexer.hh" +#include "treeifier/tokenizer.hh" #include "utils/json.hh" #include "utils/strings.hh" #include "utils/threading.hh" @@ -31,83 +32,87 @@ using std::cout; using std::size_t; using namespace ppc; -using namespace ppc::comp::tree; -using namespace ppc::comp::tree::ast; +using namespace ppc::tree; +using namespace ppc::tree::constr; void add_flags(options::parser_t &parser) { - parser.add_flag({ .name = "version", - .shorthands = "v", - .description = "Displays version and license agreement of this binary", - .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { - cout << "++C compiler\n" - << " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD + parser.add_flag({ + .name = "version", + .shorthands = "v", + .description = "Displays version and license agreement of this binary", + .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { + cout << "++C compiler\n"; + cout << " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD; #if WINDOWS - << " (Windows)" + cout << " (Windows)"; #elif LINUX - << " (Linux)" + cout << " (Linux)"; #endif - << "\n" - << " License: MIT Copyright (C) TopchetoEU\n"; - exit(0); - } }); - parser.add_flag({ .name = "help", - .shorthands = "h", - .description = "Displays a list of all flags and their meaning", - .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { - cout << "Usage: ...flags ...files\n\n" - << "Flags and file names can be interlaced\n" - << "Flags will execute in the order they're written, then compilation begins\n\n" - << "Flags:\n"; - - for (const auto &flag : parser) { - std::stringstream buff; - buff << " --" << flag.name; - - if (flag.match_type) buff << "=..."; - if (flag.shorthands.size()) { - buff << " ("; - bool first = true; - for (char shorthand : flag.shorthands) { - if (!first) buff << ","; - else first = false; - - buff << " -"; - buff << std::string { shorthand }; - } - buff << ")"; - } - - buff << " "; - - cout << buff.str(); - size_t n = buff.str().length(); - - if (flag.description.size()) { - const size_t padding = 24; - const size_t msg_width = 80 - padding; - - for (size_t i = 0; i < padding - n; i++) - cout << ' '; - - int len = flag.description.length(); - - for (size_t i = 0; i < len / msg_width; i++) { - for (size_t j = 0; j < msg_width; j++) - cout << flag.description[i * msg_width + j]; - cout << std::endl; - for (size_t j = 0; j < padding; j++) - cout << ' '; - } - - int remainder = len % msg_width; - - for (int i = 0; i < remainder; i++) - cout << flag.description[len - remainder + i]; - } - - printf("\n"); - } - } }); + cout << "\n"; + cout << " License: MIT Copyright (C) TopchetoEU\n"; + exit(0); + } + }); + parser.add_flag({ + .name = "help", + .shorthands = "h", + .description = "Displays a list of all flags and their meaning", + .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { + cout << "Usage: ...flags ...files\n\n"; + cout << "Flags and file names can be interlaced\n"; + cout << "Flags will execute in the order they're written, then compilation begins\n\n"; + cout << "Flags:\n"; + + for (const auto &flag : parser) { + std::stringstream buff; + buff << " --" << flag.name; + + if (flag.match_type) buff << "=..."; + if (flag.shorthands.size()) { + buff << " ("; + bool first = true; + for (char shorthand : flag.shorthands) { + if (!first) buff << ","; + else first = false; + + buff << " -"; + buff << std::string { shorthand }; + } + buff << ")"; + } + + buff << " "; + + cout << buff.str(); + size_t n = buff.str().length(); + + if (flag.description.size()) { + const size_t padding = 24; + const size_t msg_width = 80 - padding; + + for (size_t i = 0; i < padding - n; i++) + cout << ' '; + + int len = flag.description.length(); + + for (size_t i = 0; i < len / msg_width; i++) { + for (size_t j = 0; j < msg_width; j++) + cout << flag.description[i * msg_width + j]; + cout << std::endl; + for (size_t j = 0; j < padding; j++) + cout << ' '; + } + + int remainder = len % msg_width; + + for (int i = 0; i < remainder; i++) + cout << flag.description[len - remainder + i]; + } + + printf("\n"); + } + } + }); parser.add_flag({ .name = "silent", .shorthands = "qs", @@ -118,12 +123,14 @@ void add_flags(options::parser_t &parser) { .description = "Sets a lower limit of messages that will print. Accepted values: 'all', 'debug', 'suggestion', 'info', 'warning', 'error', 'none'", .match_type = options::MATCH_PREFIX, }); - parser.add_flag({ .name = "print-what", - .description = "Prints a 'what?' type of message (you'll see)", - .match_type = options::MATCH_PREFIX, - .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { - global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL.")); - } }); + parser.add_flag({ + .name = "print-what", + .description = "Prints a 'what?' type of message (you'll see)", + .match_type = options::MATCH_PREFIX, + .execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) { + global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL.")); + } + }); } int main(int argc, const char *argv[]) { @@ -156,9 +163,8 @@ int main(int argc, const char *argv[]) { std::ifstream f { file, std::ios_base::in }; if (!f.is_open()) throw message_t::error("The file doesn't exist.", { file }); auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f)); - auto ast = ast_ctx_t::parse(ast::parse_glob, msg_stack, tokens); - - std::cout << data::json::stringify(ast) << std::endl; + auto ast = ast_ctx_t::parse(constr::glob_parser_t(), msg_stack, tokens); + // std::cout << data::json::stringify(ast) << std::endl; } catch (const messages::message_t &msg) { msg_stack.push(msg); diff --git a/src/compiler.proj b/src/treeifier.proj similarity index 52% rename from src/compiler.proj rename to src/treeifier.proj index 6fa4f42..d34bf8b 100644 --- a/src/compiler.proj +++ b/src/treeifier.proj @@ -1,2 +1,2 @@ -compiler +treeifier utils, lang \ No newline at end of file diff --git a/src/treeifier/ast.cc b/src/treeifier/ast.cc new file mode 100644 index 0000000..6063987 --- /dev/null +++ b/src/treeifier/ast.cc @@ -0,0 +1,36 @@ +#include "treeifier/constr.hh" +#include + +using namespace ppc; +using namespace ppc::data; +using namespace ppc::lang; +using namespace ppc::tree::constr; + +// ppc::tree::constr::inspoint_t &ast_ctx_t::group(const std::string &name) { +// if (groups.find(name) == groups.end()) return groups[name] = {}; +// else return groups[name]; +// } + +ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): + messages(messages), tokens(tokens) { + // group("$_exp_val") + // .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("$_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("$_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/treeifier/constr/glob.cc b/src/treeifier/constr/glob.cc new file mode 100644 index 0000000..cc23fa6 --- /dev/null +++ b/src/treeifier/constr/glob.cc @@ -0,0 +1,41 @@ +#include "treeifier/constr/glob.hh" +#include "treeifier/constr/helper.hh" +#include "treeifier/constr/nmsp.hh" + +using namespace ppc::tree::constr; + +bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, glob_t &out) const { + parse_helper_t h(ctx, res_i); + out = {}; + + if (h.ended()) return h.submit(false); + + if (h.curr().is_identifier("namespace")) { + h.advance("Expected a namespace"); + h.force_parse(nmsp_parser_t(), "Expected a namespace.", out.nmsp); + + if (!h.curr().is_operator(operator_t::SEMICOLON)) { + ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1))); + } + + if (!h.try_advance()) return h.submit(false); + } + + while (h.curr().is_identifier("import")) { + loc_namespace_name_t res; + + h.advance("Expected a namespace"); + h.force_parse(nmsp_parser_t(), "Expected a namespace.", res); + + if (!h.curr().is_operator(operator_t::SEMICOLON)) { + ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1))); + } + + out.imports.push_back(res); + if (!h.try_advance()) return h.submit(false); + } + + if (!h.ended()) h.err("Invalid token."); + + return h.submit(false); +} diff --git a/src/treeifier/constr/identifier.cc b/src/treeifier/constr/identifier.cc new file mode 100644 index 0000000..695ec42 --- /dev/null +++ b/src/treeifier/constr/identifier.cc @@ -0,0 +1,16 @@ +#include "treeifier/constr/helper.hh" +#include "treeifier/constr/identifier.hh" + +using namespace ppc::tree::constr; + +bool identifier_parser_t::operator()(ast_ctx_t& ctx, size_t& res_i, located_t& out) const { + parse_helper_t h(ctx, res_i); + + if (h.ended()) return false; + + if (h.curr().is_identifier()) { + out = located_t(h.loc(), h.curr().identifier()); + return h.submit(); + } + else return false; +} diff --git a/src/treeifier/constr/nmsp.cc b/src/treeifier/constr/nmsp.cc new file mode 100644 index 0000000..942600a --- /dev/null +++ b/src/treeifier/constr/nmsp.cc @@ -0,0 +1,26 @@ +#include "treeifier/constr/helper.hh" +#include "treeifier/constr/nmsp.hh" + +using namespace ppc::tree::constr; + +bool nmsp_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, loc_namespace_name_t &out) const { + parse_helper_t h(ctx, res_i); + + if (h.ended()) return false; + + out.clear(); + located_t val; + + if (!h.parse(identifier_parser_t(), val)) return false; + else out.push_back(val); + + while (true) { + if (h.ended()) break; + if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break; + h.advance("Expected an identifier."); + h.force_parse(identifier_parser_t(), "Expected an identifier.", val); + out.push_back(val); + } + + return h.submit(false); +} diff --git a/src/compiler/treeifier/lexer.cc b/src/treeifier/lexer.cc similarity index 98% rename from src/compiler/treeifier/lexer.cc rename to src/treeifier/lexer.cc index b12b3b9..d17352f 100644 --- a/src/compiler/treeifier/lexer.cc +++ b/src/treeifier/lexer.cc @@ -1,10 +1,10 @@ -#include "compiler/treeifier/lexer.hh" +#include "treeifier/lexer.hh" #include "utils/message.hh" #include using namespace ppc; using namespace ppc::messages; -using namespace ppc::comp::tree::lex; +using namespace ppc::tree::lex; struct res_t; using lexlet_t = res_t (*)(char c, std::vector &tok); diff --git a/src/compiler/treeifier/operators.cc b/src/treeifier/operators.cc similarity index 89% rename from src/compiler/treeifier/operators.cc rename to src/treeifier/operators.cc index 584c264..d3fc66a 100644 --- a/src/compiler/treeifier/operators.cc +++ b/src/treeifier/operators.cc @@ -1,8 +1,8 @@ -#include "compiler/treeifier/tokenizer.hh" +#include "treeifier/tokenizer.hh" #include -using namespace ppc::comp::tree; -using namespace ppc::comp; +using namespace ppc; +using namespace ppc::tree; using namespace std::string_literals; diff --git a/src/compiler/treeifier/tokenizer.cc b/src/treeifier/tokenizer.cc similarity index 98% rename from src/compiler/treeifier/tokenizer.cc rename to src/treeifier/tokenizer.cc index 2da0e7d..b03b009 100644 --- a/src/compiler/treeifier/tokenizer.cc +++ b/src/treeifier/tokenizer.cc @@ -1,11 +1,11 @@ -#include "compiler/treeifier/lexer.hh" -#include "compiler/treeifier/tokenizer.hh" +#include "treeifier/lexer.hh" +#include "treeifier/tokenizer.hh" #include #include using namespace ppc; using namespace messages; -using namespace comp::tree; +using namespace ppc::tree; using namespace std::string_literals; static std::vector parse_string(msg_stack_t &msg_stack, bool is_char, const lex::token_t &token) { From 2461ed1860090d08aa64df028e0579a9d5446c57 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 26 Jan 2023 10:06:39 +0200 Subject: [PATCH 05/14] chore: a lot of file restructuring --- include/lang/common.hh | 85 ++++++------- include/lang/module.hh | 162 ------------------------- include/treeifier/constr.hh | 77 +++++------- include/treeifier/constr/glob.hh | 9 -- include/treeifier/constr/helper.hh | 21 ++-- include/treeifier/constr/identifier.hh | 8 -- include/treeifier/constr/inspoint.hh | 51 ++++++++ include/treeifier/constr/nmsp.hh | 9 -- include/utils/threading.hh | 14 +-- src/lang/common.cc | 12 +- src/lang/module.cc | 25 +--- src/main.proj | 2 +- src/main/main.cc | 4 +- src/treeifier/constr.cc | 48 ++++++++ src/treeifier/constr/glob.cc | 9 +- src/treeifier/constr/identifier.cc | 16 --- src/treeifier/constr/nmsp.cc | 26 ---- 17 files changed, 198 insertions(+), 380 deletions(-) delete mode 100644 include/lang/module.hh delete mode 100644 include/treeifier/constr/glob.hh delete mode 100644 include/treeifier/constr/identifier.hh create mode 100644 include/treeifier/constr/inspoint.hh delete mode 100644 include/treeifier/constr/nmsp.hh create mode 100644 src/treeifier/constr.cc delete mode 100644 src/treeifier/constr/identifier.cc delete mode 100644 src/treeifier/constr/nmsp.cc diff --git a/include/lang/common.hh b/include/lang/common.hh index ba966b9..0f3ec89 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -4,29 +4,29 @@ #include namespace ppc::lang { - struct namespace_name_t: public std::vector { + struct nmsp_t: public std::vector { using base = std::vector; - int compare(const namespace_name_t &other) const; + int compare(const nmsp_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; } + bool operator==(const nmsp_t &other) const { return compare(other) == 0; } + bool operator!=(const nmsp_t &other) const { return compare(other) != 0; } + bool operator<(const nmsp_t &other) const { return compare(other) < 0; } + bool operator<=(const nmsp_t &other) const { return compare(other) <= 0; } + bool operator>(const nmsp_t &other) const { return compare(other) > 0; } + bool operator>=(const nmsp_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()) { } + nmsp_t() { } + nmsp_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 { +struct std::hash { + std::size_t operator()(const ppc::lang::nmsp_t& k) const { size_t res = 0; for (auto &el : k) { @@ -41,55 +41,46 @@ struct std::hash { #include "utils/location.hh" namespace ppc::lang { - template - struct located_t: T { + template + struct located_t: ParserT { location_t location; - located_t(location_t loc, const T &val): T(val), location(loc) { } - located_t(const T &val): T(val), location(location_t::NONE) { } + located_t(location_t loc, const ParserT &val): ParserT(val), location(loc) { } + located_t(const ParserT &val): ParserT(val), location(location_t::NONE) { } located_t() { } }; - template - struct slocated_t { - T value; - location_t location; - bool operator ==(const slocated_t &other) { - return value == other.value && location == other.location; - } - bool operator !=(const slocated_t &other) { - return !(*this == other); - } - - slocated_t(location_t loc, const T &val): value(val), location(loc) { } - slocated_t(const T &val): value(val), location(location_t::NONE) { } - slocated_t() { } - }; - - struct loc_namespace_name_t: public std::vector> { + struct loc_nmsp_t: public std::vector> { using base = std::vector>; - int compare(const loc_namespace_name_t &other) const; + int compare(const loc_nmsp_t &other) const; - bool operator==(const loc_namespace_name_t &other) const { return compare(other) == 0; } - bool operator!=(const loc_namespace_name_t &other) const { return compare(other) != 0; } - bool operator<(const loc_namespace_name_t &other) const { return compare(other) < 0; } - bool operator<=(const loc_namespace_name_t &other) const { return compare(other) <= 0; } - bool operator>(const loc_namespace_name_t &other) const { return compare(other) > 0; } - bool operator>=(const loc_namespace_name_t &other) const { return compare(other) >= 0; } + bool operator==(const loc_nmsp_t &other) const { return compare(other) == 0; } + bool operator!=(const loc_nmsp_t &other) const { return compare(other) != 0; } + bool operator<(const loc_nmsp_t &other) const { return compare(other) < 0; } + bool operator<=(const loc_nmsp_t &other) const { return compare(other) <= 0; } + bool operator>(const loc_nmsp_t &other) const { return compare(other) > 0; } + bool operator>=(const loc_nmsp_t &other) const { return compare(other) >= 0; } - namespace_name_t strip_location() const; + nmsp_t strip_location() const; + operator nmsp_t() { return strip_location(); } operator std::string() const { return to_string(); } std::string to_string() const; - loc_namespace_name_t() { } - loc_namespace_name_t(std::initializer_list> segments): base(segments.begin(), segments.end()) { } + loc_nmsp_t() { } + loc_nmsp_t(std::initializer_list> segments): base(segments.begin(), segments.end()) { } }; - bool is_identifier_valid(messages::msg_stack_t &msg_stack, ppc::location_t location, const std::string &name); - inline bool is_identifier_valid(const std::string &name) { - messages::msg_stack_t ms; - return is_identifier_valid(ms, { }, name); + template + bool resolve_name(const SetT &defs, const nmsp_t &src, const nmsp_t &target) { + if (src == target) return true; + + for (auto &it : defs) { + nmsp_t val = (nmsp_t)it; + val.insert(val.end(), src.begin(), src.end()); + + if (val == target) return true; + } } } \ No newline at end of file diff --git a/include/lang/module.hh b/include/lang/module.hh deleted file mode 100644 index 8205604..0000000 --- a/include/lang/module.hh +++ /dev/null @@ -1,162 +0,0 @@ -#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/include/treeifier/constr.hh b/include/treeifier/constr.hh index cd8d39a..2278ccb 100644 --- a/include/treeifier/constr.hh +++ b/include/treeifier/constr.hh @@ -20,20 +20,27 @@ namespace ppc::tree::constr { struct ast_ctx_t; struct glob_t { - loc_namespace_name_t nmsp; - std::vector imports; + loc_nmsp_t nmsp; + std::vector imports; + + #ifdef PROFILE_debug + void print() const { + std::cout << "Namespace: " << nmsp.to_string() << "\n"; + std::cout << "Imports:\n"; + for (auto &imp : imports) { + std::cout << " - " << imp.to_string() << "\n"; + } + } + #endif + }; + struct exp_t: public named_t { }; - template + template class parser_t { public: - virtual bool operator()(ast_ctx_t &ctx, size_t &res_i, T &out) const = 0; - virtual bool simplify(ast_ctx_t &ctx, GlobT &glob, T &val) const = 0; -#ifdef PROFILE_debug - virtual void print(const T &val) { - std::cout << "(unknown)"; - } -#endif + virtual bool operator()(ast_ctx_t &ctx, size_t &res_i, ParserT &out) const = 0; + virtual bool simplify(ast_ctx_t &ctx, GlobT &glob, ParserT &val) const = 0; }; @@ -41,50 +48,24 @@ namespace ppc::tree::constr { public: msg_stack_t &messages; std::vector &tokens; - loc_namespace_name_t nmsp; + loc_nmsp_t nmsp; ast_ctx_t &operator=(const ast_ctx_t &other) = delete; + ast_ctx_t(msg_stack_t &messages, std::vector &tokens): + messages(messages), tokens(tokens) { } + }; - template - bool parse(const parser_t &parser, size_t &i, T &out) { - return parser(*this, i, out); - } - - template - static T parse(const parser_t &glob, msg_stack_t &messages, std::vector &tokens) { - ast_ctx_t ctx(messages, tokens); - T res; - size_t i = 0; - - if (!ctx.parse(glob, i, res)) throw message_t::error("Failed to compile."); - return res; - } + bool parse_identifier(ast_ctx_t &ctx, size_t &res_i, located_t &out); + bool parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out); + bool parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, nmsp_t nmsp); - ast_ctx_t(msg_stack_t &messages, std::vector &tokens); + class exp_parser_t { + public: + bool operator()(ast_ctx_t &ctx, glob_t &out) const; }; - - template - class inspoint_t { - private: - std::map named_parsers; - std::set unnamed_parsers; - std::map parsers; + class glob_parser_t { public: - inspoint_t &replace(const std::string &name, const T &parser) { - auto it = parsers.find(name); - - if (parsers.find(name) == parsers.end()) { - throw "The parser '" + name + "' isn't in the group."; - } - - it->second = parser; - - return *this; - } - inspoint_t &add(const std::string &name, const T &parser); - inspoint_t &add(const std::string &name, const lang::namespace_name_t &identifier, const T &parser); - - bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const; + bool operator()(ast_ctx_t &ctx, glob_t &out) const; }; // parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp; diff --git a/include/treeifier/constr/glob.hh b/include/treeifier/constr/glob.hh deleted file mode 100644 index 9303979..0000000 --- a/include/treeifier/constr/glob.hh +++ /dev/null @@ -1,9 +0,0 @@ -#include "treeifier/constr.hh" - -namespace ppc::tree::constr { - class glob_parser_t: public parser_t { - public: - bool operator()(ast_ctx_t &ctx, size_t &res_i, glob_t &out) const override; - bool simplify(ast_ctx_t &ctx, glob_t &glob, glob_t &val) const override { return false; } - }; -} \ No newline at end of file diff --git a/include/treeifier/constr/helper.hh b/include/treeifier/constr/helper.hh index c91f3a9..bfb7186 100644 --- a/include/treeifier/constr/helper.hh +++ b/include/treeifier/constr/helper.hh @@ -7,7 +7,7 @@ using namespace ppc::tree; using namespace ppc::tree::constr; namespace ppc::tree::constr { - struct parse_helper_t { + struct helper_t { private: ast_ctx_t &ctx; size_t &res_i; @@ -104,28 +104,25 @@ namespace ppc::tree::constr { throw_ended(reason); } - template - bool parse(const parser_t &parser, T &out) { - return ctx.parse(parser, i, out); + template + bool parse(const ParserT &parser, ArgsT &...args) { + return parser(ctx, i, args...); } - template - void force_parse(const parser_t &parser, std::string message, T &out) { + template + void force_parse(const ParserT &parser, std::string message, ArgsT &...args) { throw_ended(message); - bool success; try { - success = parse(parser, out); + if (!parser(ctx, i, args...)) err(message); } catch (const message_t &msg) { ctx.messages.push(msg); - success = false; + err(message); } - - if (!success) err(message); } - parse_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { + helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { this->i = i; } }; diff --git a/include/treeifier/constr/identifier.hh b/include/treeifier/constr/identifier.hh deleted file mode 100644 index b16e615..0000000 --- a/include/treeifier/constr/identifier.hh +++ /dev/null @@ -1,8 +0,0 @@ -#include "treeifier/constr.hh" - -namespace ppc::tree::constr { - struct identifier_parser_t: public parser_t> { - bool operator()(ast_ctx_t &ctx, size_t &res_i, located_t &out) const override; - bool simplify(ast_ctx_t &ctx, glob_t &glob, located_t &val) const override { return false; } - }; -} \ No newline at end of file diff --git a/include/treeifier/constr/inspoint.hh b/include/treeifier/constr/inspoint.hh new file mode 100644 index 0000000..96bb632 --- /dev/null +++ b/include/treeifier/constr/inspoint.hh @@ -0,0 +1,51 @@ +#include "treeifier/constr.hh" +#include "treeifier/constr/helper.hh" +#include "treeifier/constr/nmsp.hh" + +namespace ppc::tree::constr { + struct named_t { + virtual std::string name() = 0; + virtual ~named_t() = default; + + #ifdef PROFILE_debug + virtual void print() { std::cout << "(" << name() << ")"; } + #endif + }; + + template + class inspoint_t { + private: + std::map> parsers; + public: + inspoint_t &add(const ParserT &parser, bool replace = false) { + const std::string &name = parser.name(); + auto it = parsers.find(name); + if (it != parsers.end()) { + if (!replace) throw "The parser '" + name + "' is already in the group."; + it->second = std::make_unique(parser); + } + else { + parsers.emplace(name, std::make_unique(parser)); + } + + return *this; + } + + bool operator()(ast_ctx_t &ctx, size_t &i, std::unique_ptr &out) const override { + helper_t h(ctx, i); + + if (h.ended()) return false; + + for (std::pair> &pair : parsers) { + ResT res; + + if (pair.second(ctx, i, res)) { + out = std::make_unique(res); + return true; + } + } + + return false; + } + }; +} \ No newline at end of file diff --git a/include/treeifier/constr/nmsp.hh b/include/treeifier/constr/nmsp.hh deleted file mode 100644 index 0c10a85..0000000 --- a/include/treeifier/constr/nmsp.hh +++ /dev/null @@ -1,9 +0,0 @@ -#include "treeifier/constr/identifier.hh" -#include "treeifier/constr.hh" - -namespace ppc::tree::constr { - struct nmsp_parser_t: public parser_t { - bool operator()(ast_ctx_t &ctx, size_t &res_i, loc_namespace_name_t &out) const override; - bool simplify(ast_ctx_t &ctx, glob_t &glob, loc_namespace_name_t &val) const override { return false; } - }; -} \ No newline at end of file diff --git a/include/utils/threading.hh b/include/utils/threading.hh index 51a7a5a..8d50a7a 100644 --- a/include/utils/threading.hh +++ b/include/utils/threading.hh @@ -7,8 +7,8 @@ #endif namespace ppc::threading { - template - using thread_func_t = int (THREAD *)(T *data); + template + using thread_func_t = int (THREAD *)(ParserT *data); using empty_thread_func_t = int (THREAD *)(); struct thread_t { @@ -20,13 +20,13 @@ namespace ppc::threading { int join() const; thread_t(void *handle) { this->handle = handle; } - template - inline static thread_t start(thread_func_t func, const T &args) { - T _args = args; + template + inline static thread_t start(thread_func_t func, const ParserT &args) { + ParserT _args = args; return start_impl((void*)func, &_args); } - template - inline static thread_t start(thread_func_t func, T &args) { + template + inline static thread_t start(thread_func_t func, ParserT &args) { return start_impl((void*)func, &args); } inline static thread_t start(empty_thread_func_t func) { diff --git a/src/lang/common.cc b/src/lang/common.cc index 7c5a004..d4cbf5c 100644 --- a/src/lang/common.cc +++ b/src/lang/common.cc @@ -2,7 +2,7 @@ #include namespace ppc::lang { - std::string loc_namespace_name_t::to_string() const { + std::string loc_nmsp_t::to_string() const { std::stringstream res; for (size_t i = 0; i < size(); i++) { @@ -12,7 +12,7 @@ namespace ppc::lang { return res.str(); } - std::string namespace_name_t::to_string() const { + std::string nmsp_t::to_string() const { std::stringstream res; for (size_t i = 0; i < size(); i++) { @@ -23,7 +23,7 @@ namespace ppc::lang { return res.str(); } - int namespace_name_t::compare(const namespace_name_t &b) const { + int nmsp_t::compare(const nmsp_t &b) const { const auto &a = *this; for (size_t i = 0; i < a.size() && i < b.size(); i++) { auto cmp = a[i].compare(b[i]); @@ -34,7 +34,7 @@ namespace ppc::lang { else if (a.size() == b.size()) return 0; else return -1; } - int loc_namespace_name_t::compare(const loc_namespace_name_t &b) const { + int loc_nmsp_t::compare(const loc_nmsp_t &b) const { const auto &a = *this; for (size_t i = 0; i < a.size() && i < b.size(); i++) { auto cmp = a[i].compare(b[i]); @@ -46,8 +46,8 @@ namespace ppc::lang { else return -1; } - namespace_name_t loc_namespace_name_t::strip_location() const { - namespace_name_t res; + nmsp_t loc_nmsp_t::strip_location() const { + nmsp_t res; for (const auto &el : *this) { res.push_back(el); diff --git a/src/lang/module.cc b/src/lang/module.cc index 1b91993..123f3c8 100644 --- a/src/lang/module.cc +++ b/src/lang/module.cc @@ -59,7 +59,7 @@ field_t &definition_t::get_field() { } -statement_t statement_t::call(const namespace_name_t &func) { +statement_t statement_t::call(const nmsp_t &func) { return { CALL, { .call = new auto(func) } }; } statement_t statement_t::stack(int64_t stack) { @@ -68,26 +68,3 @@ statement_t statement_t::stack(int64_t 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 diff --git a/src/main.proj b/src/main.proj index ba8a6bc..3b14ac7 100644 --- a/src/main.proj +++ b/src/main.proj @@ -1,2 +1,2 @@ main -utils, treeifier \ No newline at end of file +utils, treeifier, lang \ No newline at end of file diff --git a/src/main/main.cc b/src/main/main.cc index ce28519..a920688 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -164,7 +164,9 @@ int main(int argc, const char *argv[]) { if (!f.is_open()) throw message_t::error("The file doesn't exist.", { file }); auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f)); auto ast = ast_ctx_t::parse(constr::glob_parser_t(), msg_stack, tokens); - // std::cout << data::json::stringify(ast) << std::endl; + #ifdef PROFILE_debug + ast.print(); + #endif } catch (const messages::message_t &msg) { msg_stack.push(msg); diff --git a/src/treeifier/constr.cc b/src/treeifier/constr.cc new file mode 100644 index 0000000..bb5af9e --- /dev/null +++ b/src/treeifier/constr.cc @@ -0,0 +1,48 @@ +#include "treeifier/constr.hh" +#include "treeifier/constr/helper.hh" +#include "lang/common.hh" + +using namespace ppc::tree::constr; + +bool ppc::tree::constr::parse_identifier(ast_ctx_t &ctx, size_t &res_i, located_t &out) { + helper_t h(ctx, res_i); + + if (h.ended()) return false; + + if (h.curr().is_identifier()) { + out = located_t(h.loc(), h.curr().identifier()); + return h.submit(); + } + else return false; +} + +bool ppc::tree::constr::parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out) { + helper_t h(ctx, res_i); + + if (h.ended()) return false; + + out.clear(); + located_t val; + + if (!h.parse(parse_identifier, val)) return false; + else out.push_back(val); + + while (true) { + if (h.ended()) break; + if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break; + h.advance("Expected an identifier."); + h.force_parse(parse_identifier, "Expected an identifier.", val); + out.push_back(val); + } + + return h.submit(false); +} + +bool ppc::tree::constr::parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, glob_t glob, nmsp_t nmsp) { + helper_t h(ctx, res_i); + nmsp_t src; + + if (!h.parse(parse_nmsp, src)) return false; + if (resolve_name(glob.imports, src, nmsp)) return h.submit(false); + else return false; +} diff --git a/src/treeifier/constr/glob.cc b/src/treeifier/constr/glob.cc index cc23fa6..5dfead8 100644 --- a/src/treeifier/constr/glob.cc +++ b/src/treeifier/constr/glob.cc @@ -4,15 +4,16 @@ using namespace ppc::tree::constr; -bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, glob_t &out) const { - parse_helper_t h(ctx, res_i); +bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, glob_t &out) const { + size_t res_i = 0; + helper_t h(ctx, res_i); out = {}; if (h.ended()) return h.submit(false); if (h.curr().is_identifier("namespace")) { h.advance("Expected a namespace"); - h.force_parse(nmsp_parser_t(), "Expected a namespace.", out.nmsp); + h.force_parse(parse_nmsp, "Expected a namespace.", out.nmsp); if (!h.curr().is_operator(operator_t::SEMICOLON)) { ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1))); @@ -22,7 +23,7 @@ bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, } while (h.curr().is_identifier("import")) { - loc_namespace_name_t res; + loc_nmsp_t res; h.advance("Expected a namespace"); h.force_parse(nmsp_parser_t(), "Expected a namespace.", res); diff --git a/src/treeifier/constr/identifier.cc b/src/treeifier/constr/identifier.cc deleted file mode 100644 index 695ec42..0000000 --- a/src/treeifier/constr/identifier.cc +++ /dev/null @@ -1,16 +0,0 @@ -#include "treeifier/constr/helper.hh" -#include "treeifier/constr/identifier.hh" - -using namespace ppc::tree::constr; - -bool identifier_parser_t::operator()(ast_ctx_t& ctx, size_t& res_i, located_t& out) const { - parse_helper_t h(ctx, res_i); - - if (h.ended()) return false; - - if (h.curr().is_identifier()) { - out = located_t(h.loc(), h.curr().identifier()); - return h.submit(); - } - else return false; -} diff --git a/src/treeifier/constr/nmsp.cc b/src/treeifier/constr/nmsp.cc deleted file mode 100644 index 942600a..0000000 --- a/src/treeifier/constr/nmsp.cc +++ /dev/null @@ -1,26 +0,0 @@ -#include "treeifier/constr/helper.hh" -#include "treeifier/constr/nmsp.hh" - -using namespace ppc::tree::constr; - -bool nmsp_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, loc_namespace_name_t &out) const { - parse_helper_t h(ctx, res_i); - - if (h.ended()) return false; - - out.clear(); - located_t val; - - if (!h.parse(identifier_parser_t(), val)) return false; - else out.push_back(val); - - while (true) { - if (h.ended()) break; - if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break; - h.advance("Expected an identifier."); - h.force_parse(identifier_parser_t(), "Expected an identifier.", val); - out.push_back(val); - } - - return h.submit(false); -} From fafd2ad864a293d9da63f2e1cd5d3d793616f254 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 26 Jan 2023 16:46:50 +0200 Subject: [PATCH 06/14] chore: add lsinc for more efficient makescript --- .gitignore | 4 +- scripts/common.mak | 5 ++- scripts/ls.mak | 9 ++++ scripts/lsproj.mak | 3 -- src/lsinc.cc | 109 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 scripts/ls.mak delete mode 100644 scripts/lsproj.mak create mode 100644 src/lsinc.cc diff --git a/.gitignore b/.gitignore index 0e936b5..715003a 100644 --- a/.gitignore +++ b/.gitignore @@ -19,11 +19,11 @@ !src/*/**/*.h !src/*/**/*.hh !src/*.proj -!src/lsproj.cc +!src/ls*.cc !scripts !scripts/common.mak -!scripts/lsproj.mak +!scripts/ls.mak !scripts/install.bat !scripts/uninstall.bat diff --git a/scripts/common.mak b/scripts/common.mak index c9091f3..e5f8973 100644 --- a/scripts/common.mak +++ b/scripts/common.mak @@ -1,7 +1,8 @@ export lsproj = $(bin)/lsproj$(exe) +export lsinc = $(bin)/lsinc$(exe) export flags += "-I$(inc)" -D$(OS) -DPPC_VERSION_MAJOR=$(version-major) -DPPC_VERSION_MINOR=$(version-minor) -DPPC_VERSION_BUILD=$(version-build) -$(shell make -f scripts/lsproj.mak lsproj=$(lsproj) src=$(src) $(lsproj)) +$(shell make -f scripts/ls.mak lsinc=$(lsinc) lsproj=$(lsproj) src=$(src) "flags=$(flags)" all) rwildcard=$(foreach d, $(wildcard $(1:=/*)),\ $(call rwildcard,$d,$2)\ @@ -52,7 +53,7 @@ $(bin)/lib$(lib)%$(so): $$(call frdeps,$$*) $$(call binaries,$$*) $(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 $(shell $(lsinc) $(inc) $(src)/%.cc) $(call mkdir,$(dir $@)) $(CXX) -fPIC -c $(flags) $< -o $@ echo - Compiling '$*.cc'... diff --git a/scripts/ls.mak b/scripts/ls.mak new file mode 100644 index 0000000..0d4e125 --- /dev/null +++ b/scripts/ls.mak @@ -0,0 +1,9 @@ +all: $(lsproj) $(lsinc) + +$(lsproj): $(src)/lsproj.cc + $(call mkdir,$(dir $@)) + $(CXX) $(flags) $^ -o $@ + +$(lsinc): $(src)/lsinc.cc + $(call mkdir,$(dir $@)) + $(CXX) $(flags) $^ -o $@ \ No newline at end of file diff --git a/scripts/lsproj.mak b/scripts/lsproj.mak deleted file mode 100644 index 6d49d5a..0000000 --- a/scripts/lsproj.mak +++ /dev/null @@ -1,3 +0,0 @@ -$(lsproj): $(src)/lsproj.cc - $(call mkdir,$(dir $@)) - $(CXX) $^ -o $@ \ No newline at end of file diff --git a/src/lsinc.cc b/src/lsinc.cc new file mode 100644 index 0000000..8bb4ebb --- /dev/null +++ b/src/lsinc.cc @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::string_literals; +namespace fs = std::filesystem; + +static inline void ltrim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); +} +static inline void rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); +} +static inline void trim(std::string &s) { + rtrim(s); + ltrim(s); +} +static bool read_line(std::istream &str, std::string &res) { + if (str.eof()) return false; + std::getline(str, res); + trim(res); + return true; +} + +fs::path find_file(fs::path original, fs::path include) { + if (fs::exists(original)) return original; + if (fs::exists(include / original)) return include / original; + return original; +} + +bool get_import(std::string line, std::string &import) { + if (line.rfind("#include") != 0) return false; + line = line.substr(8); + trim(line); + if (line.length() < 3) throw "Invalid import syntax."s; + if (line[0] == '<') return false; + if (line[0] == '"') { + if (line[line.length() - 1] != '"') throw "Invalid import syntax."s; + import = line.substr(1, line.length() - 2); + return true; + } + + throw "Invalid import syntax."s; +} + +void get_imports(fs::path file, fs::path include, std::set &res) { + static std::set parents = { }; + + if (!parents.emplace(file).second) { + throw "Circular dependency encountered."s; + } + + std::ifstream f(file.string()); + if (f.is_open() && !f.eof()) { + std::string line; + + while (read_line(f, line)) { + std::string import; + if (get_import(line, import)) { + auto child = find_file(import, include); + res.emplace(child); + get_imports(child, include, res); + } + } + } + + parents.erase(file); +} + +int main(int argc, char **argv) { + try { + argc--; + argv++; + + if (argc == 0) { + throw "Incorrect usage. Syntax: [inc-path] [files...]."s; + return -1; + } + + fs::path inc(argv[0]); + std::set res; + + for (int i = 1; i < argc; i++) { + fs::path file(argv[i]); + get_imports(file, inc, res); + } + + for (auto &i : res) { + std::cout << i.string() << "\n"; + } + + + return 0; + } + catch (std::string err) { + std::cerr << "Error: " << err << std::endl; + } + + return -1; +} \ No newline at end of file From 99cae2ee78b9ad684fa723330095323d7051f1bb Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 26 Jan 2023 18:47:20 +0200 Subject: [PATCH 07/14] fix: random bugs --- include/lang/common.hh | 8 +++-- include/treeifier/constr.hh | 11 ++---- src/lang/module.cc | 70 ------------------------------------ src/lsproj.cc | 1 - src/main/main.cc | 7 ++-- src/treeifier/constr.cc | 2 +- src/treeifier/constr/glob.cc | 5 ++- 7 files changed, 14 insertions(+), 90 deletions(-) delete mode 100644 src/lang/module.cc diff --git a/include/lang/common.hh b/include/lang/common.hh index 0f3ec89..c81a5c5 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -63,10 +63,10 @@ namespace ppc::lang { bool operator>=(const loc_nmsp_t &other) const { return compare(other) >= 0; } nmsp_t strip_location() const; + std::string to_string() const; operator nmsp_t() { return strip_location(); } operator std::string() const { return to_string(); } - std::string to_string() const; loc_nmsp_t() { } loc_nmsp_t(std::initializer_list> segments): base(segments.begin(), segments.end()) { } @@ -76,11 +76,13 @@ namespace ppc::lang { bool resolve_name(const SetT &defs, const nmsp_t &src, const nmsp_t &target) { if (src == target) return true; - for (auto &it : defs) { - nmsp_t val = (nmsp_t)it; + for (const auto &it : defs) { + nmsp_t val = (const nmsp_t&)(it); val.insert(val.end(), src.begin(), src.end()); if (val == target) return true; } + + return false; } } \ No newline at end of file diff --git a/include/treeifier/constr.hh b/include/treeifier/constr.hh index 2278ccb..5a8d2fa 100644 --- a/include/treeifier/constr.hh +++ b/include/treeifier/constr.hh @@ -33,8 +33,6 @@ namespace ppc::tree::constr { } #endif }; - struct exp_t: public named_t { - }; template class parser_t { @@ -51,18 +49,13 @@ namespace ppc::tree::constr { loc_nmsp_t nmsp; ast_ctx_t &operator=(const ast_ctx_t &other) = delete; - ast_ctx_t(msg_stack_t &messages, std::vector &tokens): - messages(messages), tokens(tokens) { } + ast_ctx_t(msg_stack_t &messages, std::vector &tokens); }; bool parse_identifier(ast_ctx_t &ctx, size_t &res_i, located_t &out); bool parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out); - bool parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, nmsp_t nmsp); + bool parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, glob_t glob, nmsp_t nmsp); - class exp_parser_t { - public: - bool operator()(ast_ctx_t &ctx, glob_t &out) const; - }; class glob_parser_t { public: bool operator()(ast_ctx_t &ctx, glob_t &out) const; diff --git a/src/lang/module.cc b/src/lang/module.cc deleted file mode 100644 index 123f3c8..0000000 --- a/src/lang/module.cc +++ /dev/null @@ -1,70 +0,0 @@ -#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 nmsp_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 }; -} diff --git a/src/lsproj.cc b/src/lsproj.cc index f1d3dc7..7579810 100644 --- a/src/lsproj.cc +++ b/src/lsproj.cc @@ -51,7 +51,6 @@ std::string read_str(std::istream &f, const std::string &skip_chars, const std:: project_t read_project(std::istream &f) { int end_ch; std::string name = read_str(f, " \v\t\r\n", "\n", end_ch); - std::size_t cap = 16, n = 0; std::vector deps {}; if (name.length() == 0) { diff --git a/src/main/main.cc b/src/main/main.cc index a920688..aa491e2 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -18,7 +18,6 @@ #include "./opions.hh" #include "treeifier/constr.hh" -#include "treeifier/constr/glob.hh" #include "treeifier/lexer.hh" #include "treeifier/tokenizer.hh" #include "utils/json.hh" @@ -163,9 +162,11 @@ int main(int argc, const char *argv[]) { std::ifstream f { file, std::ios_base::in }; if (!f.is_open()) throw message_t::error("The file doesn't exist.", { file }); auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f)); - auto ast = ast_ctx_t::parse(constr::glob_parser_t(), msg_stack, tokens); + glob_t glob; + auto ctx = ast_ctx_t(msg_stack, tokens); + glob_parser_t()(ctx, glob); #ifdef PROFILE_debug - ast.print(); + glob.print(); #endif } catch (const messages::message_t &msg) { diff --git a/src/treeifier/constr.cc b/src/treeifier/constr.cc index bb5af9e..ce7ff52 100644 --- a/src/treeifier/constr.cc +++ b/src/treeifier/constr.cc @@ -40,7 +40,7 @@ bool ppc::tree::constr::parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &ou bool ppc::tree::constr::parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, glob_t glob, nmsp_t nmsp) { helper_t h(ctx, res_i); - nmsp_t src; + loc_nmsp_t src; if (!h.parse(parse_nmsp, src)) return false; if (resolve_name(glob.imports, src, nmsp)) return h.submit(false); diff --git a/src/treeifier/constr/glob.cc b/src/treeifier/constr/glob.cc index 5dfead8..d150cf2 100644 --- a/src/treeifier/constr/glob.cc +++ b/src/treeifier/constr/glob.cc @@ -1,6 +1,5 @@ -#include "treeifier/constr/glob.hh" +#include "treeifier/constr.hh" #include "treeifier/constr/helper.hh" -#include "treeifier/constr/nmsp.hh" using namespace ppc::tree::constr; @@ -26,7 +25,7 @@ bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, glob_t &out) c loc_nmsp_t res; h.advance("Expected a namespace"); - h.force_parse(nmsp_parser_t(), "Expected a namespace.", res); + h.force_parse(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))); From 9b5a8b61ab97a82e3c7050c797cfc8ca3992e1dc Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 26 Jan 2023 19:36:33 +0200 Subject: [PATCH 08/14] fix: made build version static --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9eb6318..c1387ec 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ export output = ppc export mainmodule = main export version-major=0 export version-minor=0 +export version-build=1 ################################### ifeq ($(OS),Windows_NT) @@ -43,7 +44,7 @@ export exe=.exe export CC=gcc export CXX=g++ -export version-build=$(if $(wildcard build.version),$(shell type build.version),0) +# export version-build=$(if $(wildcard build.version),$(shell type build.version),0) export binary = $(bin)/$(output)$(version-major)-windows.exe build: version @@ -60,11 +61,10 @@ cleartmp: .ONESHELL: install: build powershell -Command "start-process cmd -verb runas -args '/K pushd %CD%&set bin=$(bin)&set output=$(output)&.\scripts\install.bat&exit'" -# .\scripts\install.bat uninstall: .\scripts\uninstall.bat -version: - cmd /c "set /a $(version-build) + 1 > build.version" +# version: +# cmd /c "set /a $(version-build) + 1 > build.version" else @@ -74,7 +74,7 @@ export mkdir=mkdir -p $$1 export rmdir=rm -rf $$1 export echo=echo "$$1" export so=.so -export version-build=$(if $(wildcard build.version),$(shell cat build.version),0) +# export version-build=$(if $(wildcard build.version),$(shell cat build.version),0) export binary = $(bin)/$(output)$(version-major)-linux build: version @@ -98,8 +98,8 @@ uninstall: echo Uninstalling ++C compiler from your system... sudo rm $(patsubst $(bin)/%.so,/usr/lib/%*.so,$(bin)/*.so) sudo rm /usr/bin/$(output) -version: - echo $$(($(version-build) + 1)) > build.version +# version: +# echo $$(($(version-build) + 1)) > build.version leak: build echo ====================== Leak scanning ======================= From 048d5716eae8c2e30a290ae0ee522a4bb505b51f Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:03:14 +0200 Subject: [PATCH 09/14] fix: make include dependencies second-expanded --- scripts/common.mak | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/common.mak b/scripts/common.mak index e5f8973..0325296 100644 --- a/scripts/common.mak +++ b/scripts/common.mak @@ -53,7 +53,8 @@ $(bin)/lib$(lib)%$(so): $$(call frdeps,$$*) $$(call binaries,$$*) $(CXX) -shared -fPIC $(flags) $(call binaries,$*) -o $@ $(ldflags) $(call ldeps,$*) -L$(bin) "-I$(inc)" echo Compiling library '$(notdir $@)'... -$(bin)/tmp/%.o: $(src)/%.cc $(shell $(lsinc) $(inc) $(src)/%.cc) +.SECONDEXPANSION: +$(bin)/tmp/%.o: $(src)/%.cc $$(shell $(lsinc) $(inc) $(src)/%.cc) $(call mkdir,$(dir $@)) $(CXX) -fPIC -c $(flags) $< -o $@ echo - Compiling '$*.cc'... From 5d9e6e10026cca93b293c637351f2540956bce20 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:13:41 +0200 Subject: [PATCH 10/14] fix: relative include paths taken into account --- src/lsinc.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lsinc.cc b/src/lsinc.cc index 8bb4ebb..b1e82cf 100644 --- a/src/lsinc.cc +++ b/src/lsinc.cc @@ -37,7 +37,7 @@ fs::path find_file(fs::path original, fs::path include) { return original; } -bool get_import(std::string line, std::string &import) { +bool get_import(std::string line, fs::path root, fs::path &import) { if (line.rfind("#include") != 0) return false; line = line.substr(8); trim(line); @@ -45,7 +45,13 @@ bool get_import(std::string line, std::string &import) { if (line[0] == '<') return false; if (line[0] == '"') { if (line[line.length() - 1] != '"') throw "Invalid import syntax."s; - import = line.substr(1, line.length() - 2); + auto path = line.substr(1, line.length() - 2); + + if (path.rfind("./") == 0 || path.rfind(".\\") == 0) { + import = root / path.substr(2); + } + else import = path; + return true; } @@ -64,8 +70,8 @@ void get_imports(fs::path file, fs::path include, std::set &res) { std::string line; while (read_line(f, line)) { - std::string import; - if (get_import(line, import)) { + fs::path import; + if (get_import(line, file.parent_path(), import)) { auto child = find_file(import, include); res.emplace(child); get_imports(child, include, res); From d6175a696d05da7f19aa854c81aa662489bb8d6c Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 27 Jan 2023 17:07:24 +0200 Subject: [PATCH 11/14] chore: improve scripts --- scripts/common.mak | 30 +++------- scripts/ls.mak | 6 +- src/lang.proj | 2 - src/lsdep.cc | 146 +++++++++++++++++++++++++++++++++++++++++++++ src/lsinc.cc | 2 +- src/lsproj.cc | 138 ------------------------------------------ src/main.proj | 2 - src/treeifier.proj | 2 - src/utils.proj | 1 - 9 files changed, 158 insertions(+), 171 deletions(-) delete mode 100644 src/lang.proj create mode 100644 src/lsdep.cc delete mode 100644 src/lsproj.cc delete mode 100644 src/main.proj delete mode 100644 src/treeifier.proj delete mode 100644 src/utils.proj diff --git a/scripts/common.mak b/scripts/common.mak index 0325296..ea06da2 100644 --- a/scripts/common.mak +++ b/scripts/common.mak @@ -1,35 +1,19 @@ -export lsproj = $(bin)/lsproj$(exe) +export lsdep = $(bin)/lsdep$(exe) export lsinc = $(bin)/lsinc$(exe) export flags += "-I$(inc)" -D$(OS) -DPPC_VERSION_MAJOR=$(version-major) -DPPC_VERSION_MINOR=$(version-minor) -DPPC_VERSION_BUILD=$(version-build) -$(shell make -f scripts/ls.mak lsinc=$(lsinc) lsproj=$(lsproj) src=$(src) "flags=$(flags)" all) +$(shell make -f scripts/ls.mak lsinc=$(lsinc) lsdep=$(lsdep) src=$(src) "flags=$(flags)" all) rwildcard=$(foreach d, $(wildcard $(1:=/*)),\ $(call rwildcard,$d,$2)\ $(filter $(subst *,%,$2),$d)\ ) -uniq=$(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) -modoutput=$(shell ./$(lsproj) $(src) $1 output) -deps=$(strip \ - $(foreach dep, $(shell ./$(lsproj) $(src) $1 deps),\ - $(if $(wildcard src/$(dep)), $(dep),\ - $(error The module '$(dep)' (dependency of '$1') doesn't exist)\ - )\ - )\ -) -rdeps=$(call uniq,$(strip \ - $(foreach dep, $(call deps,$1),\ - $(call rdeps,$(dep))\ - $(dep)\ - )\ -)) - -fdeps=$(foreach dep,$(call deps,$1),$(bin)/lib$(lib)$(call modoutput,$(dep))$(so)) -frdeps=$(foreach dep,$(call rdeps,$1),$(bin)/lib$(lib)$(call modoutput,$(dep))$(so)) - -ldeps=$(foreach dep,$(call deps,$1),-l$(lib)$(call modoutput,$(dep))) -lrdeps=$(foreach dep,$(call rdeps,$1),-l$(lib)$(call modoutput,$(dep))) +deps=$(shell $(lsdep) --dir=deps $1) +rdeps=$(shell $(lsdep) --dir=deps --rec $1) + +frdeps=$(shell $(lsdep) --dir=deps --rec --transform=$(bin)/lib$(lib)*$(so) $1) +ldeps=$(shell $(lsdep) --dir=deps --transform=-l$(lib) $1) modules = $(patsubst $(src)/%/,$(bin)/lib$(lib)%$(so),$(filter-out $(src)/$(mainmodule)/,$(wildcard $(src)/*/))) sources = $(call rwildcard,$(src)/$1,*.cc) diff --git a/scripts/ls.mak b/scripts/ls.mak index 0d4e125..c6316fa 100644 --- a/scripts/ls.mak +++ b/scripts/ls.mak @@ -1,9 +1,11 @@ -all: $(lsproj) $(lsinc) +all: $(lsdep) $(lsinc) -$(lsproj): $(src)/lsproj.cc +$(lsdep): $(src)/lsdep.cc $(call mkdir,$(dir $@)) + echo - Compiling lsdep.cc... >&2 $(CXX) $(flags) $^ -o $@ $(lsinc): $(src)/lsinc.cc + echo - Compiling lsinc.cc... >&2 $(call mkdir,$(dir $@)) $(CXX) $(flags) $^ -o $@ \ No newline at end of file diff --git a/src/lang.proj b/src/lang.proj deleted file mode 100644 index 3151a2d..0000000 --- a/src/lang.proj +++ /dev/null @@ -1,2 +0,0 @@ -lang -utils \ No newline at end of file diff --git a/src/lsdep.cc b/src/lsdep.cc new file mode 100644 index 0000000..167dd30 --- /dev/null +++ b/src/lsdep.cc @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std::string_literals; +using std::size_t; +namespace fs = std::filesystem; + +fs::path proj_dir; +bool recursive = false; +std::string prefix = "", suffix = ""; + +static inline void ltrim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); +} +static inline void rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); +} +static inline void trim(std::string &s) { + rtrim(s); + ltrim(s); +} +static bool read_line(std::istream &str, std::string &res) { + if (str.eof()) return false; + std::getline(str, res); + trim(res); + return true; +} + +void read_project_rec(const std::string &name, std::set &res, bool rec = false) { + static std::set prev; + + if (!prev.emplace(name).second) throw name + ": Circular dependency detected."; + + std::ifstream f(proj_dir / name); + std::string line; + + while (read_line(f, line)) { + if (line.find('#') != std::string::npos) { + line = line.substr(0, line.find('#')); + } + + trim(line); + + if (line.size() == 0) continue; + if (line == name) throw name + ": Depends on itself."; + + res.emplace(line); + if (rec) read_project_rec(line, res); + } + + prev.erase(name); +} + +void print_err(const std::string &error, const std::string &context) { + std::cerr << context << ": " << error; +} + +void set_transform(const std::string &val) { + size_t i = 0; + bool last_percent = false; + bool is_prefix = true; + prefix = "", suffix = ""; + + for (; i < val.length(); i++) { + if (is_prefix) { + if (val[i] == '*') { + if (last_percent) { + last_percent = false; + } + else { + last_percent = true; + continue; + } + } + else if (last_percent) { + is_prefix = false; + last_percent = false; + } + } + + if (is_prefix) prefix += val[i]; + else suffix += val[i]; + } +} + +bool process_arg(std::string arg) { + if (arg.find("--") != 0) return false; + arg = arg.substr(2); + + if (arg == "rec") { + recursive = true; + return true; + } + else if (arg.find("transform=") == 0) { + arg = arg.substr(10); + set_transform(arg); + } + else if (arg.find("dir=") == 0) { + arg = arg.substr(4); + proj_dir = arg; + } + else { + throw "Incorrect usage. Syntax: [--rec] [--transform=prefix%suffix] [--dir=dir] [projects...]"s; + } + return true; +} + +int main(int argc, const char *argv[]) { + try { + argc--; + argv++; + + std::set deps; + + while (argc > 0 && process_arg(argv[0])) { + argc--; + argv++; + } + while (argc > 0) { + // if (recursive) read_project_rec(argv[0], deps); + // else read_project(argv[0], deps); + read_project_rec(argv[0], deps, recursive); + argc--; + argv++; + } + + for (auto &dep : deps) { + std::cout << prefix + dep + suffix << std::endl; + } + + return 0; + } + catch (std::string err) { + std::cerr << "error: lsdep: " << err << std::endl; + } + return -1; +} diff --git a/src/lsinc.cc b/src/lsinc.cc index b1e82cf..003a3ea 100644 --- a/src/lsinc.cc +++ b/src/lsinc.cc @@ -108,7 +108,7 @@ int main(int argc, char **argv) { return 0; } catch (std::string err) { - std::cerr << "Error: " << err << std::endl; + std::cerr << "error: lsinc: " << err << std::endl; } return -1; diff --git a/src/lsproj.cc b/src/lsproj.cc deleted file mode 100644 index 7579810..0000000 --- a/src/lsproj.cc +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include -#include - -using namespace std::string_literals; - -struct project_t { - std::string output; - std::vector deps; -}; - -std::string read_str(std::istream &f, const std::string &skip_chars, const std::string &end_chars, int &end_char) { - std::vector res {}; - int c; - - while (true) { - c = f.get(); - auto a = end_chars.find(c); - if (c == -1 || a != std::string::npos) { - end_char = c; - return ""; - } - if ((a = skip_chars.find(c)) == std::string::npos) { - f.unget(); - break; - } - } - - while (true) { - c = f.get(); - if (c == -1 || end_chars.find(c) != std::string::npos) { - end_char = c; - break; - } - - res.push_back(c); - } - while (true) { - if (skip_chars.find(res.back()) != std::string::npos) res.pop_back(); - else break; - } - - return std::string { res.begin(), res.end() }; -} -std::string read_str(std::istream &f, const std::string &skip_chars, const std::string &end_chars) { - int end_char; - return read_str(f, skip_chars, end_chars, end_char); -} - -project_t read_project(std::istream &f) { - int end_ch; - std::string name = read_str(f, " \v\t\r\n", "\n", end_ch); - std::vector deps {}; - - if (name.length() == 0) { - throw "The name of a project may not be empty."s; - } - - if (end_ch == -1) { - return project_t { - .output = name, - .deps = deps, - }; - } - - if (name.find(',') != std::string::npos || name.find(' ') != std::string::npos) { - throw "The name of a project may not contain spaces or commas."s; - } - - while (true) { - std::string dep = read_str(f, " \v\t\r\n", ",\n", end_ch); - - if (dep.find(' ') != std::string::npos) { - throw "The name of a dependency may not contain spaces."s; - } - - if (dep.length()) { - deps.push_back(dep); - if (end_ch == '\n') break; - } - if (end_ch == -1) break; - } - - return project_t { - .output = name, - .deps = deps, - }; -} - -void print_err(const std::string &error, const std::string &context) { - std::cerr << context << ": " << error; -} - -int main(int argc, const char *argv[]) { - std::string proj_name = ""; - try { - argc--; - argv++; - - if (argc != 3) { - throw "Incorrect usage. Syntax: [src-dir] [project-name] [output|deps]."s; - } - - std::string proj_path = (std::string) argv[0] + "/" + argv[1] + ".proj"; - proj_name = argv[1]; - - std::ifstream f { proj_path, std::ios_base::in }; - - if (!f.is_open()) { - throw "The project '"s + argv[1] + "' doesn't exist."s; - } - - project_t project = read_project(f); - f.close(); - - if ((std::string) argv[2] == "output") { - std::cout << project.output; - } - else if ((std::string) argv[2] == "deps") { - for (std::string dep : project.deps) { - std::cout << dep << " "; - } - } - else { - throw "Invalid command given. Available commands: output, deps."s; - } - - std::cout << std::endl; - - return 0; - } - catch (std::string err) { - if (proj_name.length()) std::cerr << "Error: " << proj_name << ": " << err << std::endl; - else std::cerr << "Error: " << err << std::endl; - } - return -1; -} diff --git a/src/main.proj b/src/main.proj deleted file mode 100644 index 3b14ac7..0000000 --- a/src/main.proj +++ /dev/null @@ -1,2 +0,0 @@ -main -utils, treeifier, lang \ No newline at end of file diff --git a/src/treeifier.proj b/src/treeifier.proj deleted file mode 100644 index d34bf8b..0000000 --- a/src/treeifier.proj +++ /dev/null @@ -1,2 +0,0 @@ -treeifier -utils, lang \ No newline at end of file diff --git a/src/utils.proj b/src/utils.proj deleted file mode 100644 index 6625243..0000000 --- a/src/utils.proj +++ /dev/null @@ -1 +0,0 @@ -utils \ No newline at end of file From bef3c378d9bbf52c6d7b6b4581920c29828f46ff Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 27 Jan 2023 17:08:30 +0200 Subject: [PATCH 12/14] fix: add deps --- .gitignore | 4 +++- deps/lang | 1 + deps/main | 3 +++ deps/treeifier | 2 ++ deps/utils | 0 5 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 deps/lang create mode 100644 deps/main create mode 100644 deps/treeifier create mode 100644 deps/utils diff --git a/.gitignore b/.gitignore index 715003a..bb6ad7d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,6 @@ !src/*/**/*.cc !src/*/**/*.h !src/*/**/*.hh -!src/*.proj !src/ls*.cc !scripts @@ -27,6 +26,9 @@ !scripts/install.bat !scripts/uninstall.bat +!deps +!deps/* + !LICENSE !CONTRIBUTING.md !Makefile diff --git a/deps/lang b/deps/lang new file mode 100644 index 0000000..6625243 --- /dev/null +++ b/deps/lang @@ -0,0 +1 @@ +utils \ No newline at end of file diff --git a/deps/main b/deps/main new file mode 100644 index 0000000..3e6dd8b --- /dev/null +++ b/deps/main @@ -0,0 +1,3 @@ +utils +treeifier +lang \ No newline at end of file diff --git a/deps/treeifier b/deps/treeifier new file mode 100644 index 0000000..552d8af --- /dev/null +++ b/deps/treeifier @@ -0,0 +1,2 @@ +utils +lang \ No newline at end of file diff --git a/deps/utils b/deps/utils new file mode 100644 index 0000000..e69de29 From ca7a3509f9e28161730001ec415b12db3051ee33 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:40:44 +0200 Subject: [PATCH 13/14] fix: add minor version to output names --- Makefile | 6 +++--- include/lang/common.hh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c1387ec..e2e9175 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ export MAKEFLAGS += --silent -r -j export flags=-std=c++17 -Wall -Wno-main -Wno-trigraphs -Wno-missing-braces -Wno-stringop-overflow -DPROFILE_$(profile) -fdiagnostics-color=always export ldflags=-L$(bin)/$(profile) -Wl,-rpath=bin/$(profile) -export lib=ppc$(version-major)- +export lib=ppc-$(version-major).$(version-minor)- export profile=release ############# SETTINGS ############ @@ -45,7 +45,7 @@ export CC=gcc export CXX=g++ # export version-build=$(if $(wildcard build.version),$(shell type build.version),0) -export binary = $(bin)/$(output)$(version-major)-windows.exe +export binary = $(bin)/$(output)-$(version-major).$(version-minor)-windows.exe build: version echo ======================== Compiling ========================= @@ -75,7 +75,7 @@ export rmdir=rm -rf $$1 export echo=echo "$$1" export so=.so # export version-build=$(if $(wildcard build.version),$(shell cat build.version),0) -export binary = $(bin)/$(output)$(version-major)-linux +export binary = $(bin)/$(output)-$(version-major).$(version-minor)-linux build: version echo ======================== Compiling ========================= diff --git a/include/lang/common.hh b/include/lang/common.hh index c81a5c5..ed937aa 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -65,7 +65,7 @@ namespace ppc::lang { nmsp_t strip_location() const; std::string to_string() const; - operator nmsp_t() { return strip_location(); } + operator nmsp_t() const { return strip_location(); } operator std::string() const { return to_string(); } loc_nmsp_t() { } @@ -76,8 +76,8 @@ namespace ppc::lang { bool resolve_name(const SetT &defs, const nmsp_t &src, const nmsp_t &target) { if (src == target) return true; - for (const auto &it : defs) { - nmsp_t val = (const nmsp_t&)(it); + for (auto it : defs) { + nmsp_t val = (nmsp_t)(it); val.insert(val.end(), src.begin(), src.end()); if (val == target) return true; From f63ad45ccbf86ae1a9817c20a653ca5b92915115 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 10 Feb 2023 16:10:34 +0200 Subject: [PATCH 14/14] chore: major restructuring (again) --- include/ppc.hh | 13 +++-- include/treeifier/constr.hh | 53 +++++-------------- include/treeifier/constructs/glob.hh | 40 ++++++++++++++ include/treeifier/parsers/definition.hh | 13 +++++ include/treeifier/parsers/glob.hh | 16 ++++++ .../treeifier/{constr => parsers}/helper.hh | 14 ++--- .../treeifier/{constr => parsers}/inspoint.hh | 21 ++++---- src/lsinc.cc | 19 ++++++- src/main/main.cc | 10 ++-- src/treeifier/ast.cc | 8 ++- src/treeifier/constr.cc | 12 ++--- src/treeifier/constr/glob.cc | 8 +-- src/treeifier/lexer.cc | 4 +- 13 files changed, 146 insertions(+), 85 deletions(-) create mode 100644 include/treeifier/constructs/glob.hh create mode 100644 include/treeifier/parsers/definition.hh create mode 100644 include/treeifier/parsers/glob.hh rename include/treeifier/{constr => parsers}/helper.hh (92%) rename include/treeifier/{constr => parsers}/inspoint.hh (75%) diff --git a/include/ppc.hh b/include/ppc.hh index e8c22b9..7ebad24 100644 --- a/include/ppc.hh +++ b/include/ppc.hh @@ -1,10 +1,13 @@ #ifndef PPC_H #define PPC_H 1 -#include "compiler.h" - -static const int VERSION_MAJOR = PPC_VERSION_MAJOR; -static const int VERSION_MINOR = PPC_VERSION_MINOR; -static const int VERSION_BUILD = PPC_VERSION_BUILD; +#include "lang/version.hh" +namespace ppc { + static const version_t VERSION( + PPC_VERSION_MAJOR, + PPC_VERSION_MINOR, + PPC_VERSION_BUILD + ); +} #endif \ No newline at end of file diff --git a/include/treeifier/constr.hh b/include/treeifier/constr.hh index 5a8d2fa..627aed5 100644 --- a/include/treeifier/constr.hh +++ b/include/treeifier/constr.hh @@ -1,8 +1,8 @@ #pragma once +#include "utils/message.hh" #include "lang/common.hh" #include "treeifier/tokenizer.hh" -#include "utils/data.hh" #include #include #include @@ -12,54 +12,29 @@ #include using namespace std::string_literals; -using namespace ppc; -using namespace ppc::lang; -using namespace ppc::messages; -namespace ppc::tree::constr { - struct ast_ctx_t; +namespace ppc::tree { + using namespace ppc; + using namespace ppc::lang; + using namespace ppc::messages; - struct glob_t { - loc_nmsp_t nmsp; - std::vector imports; - - #ifdef PROFILE_debug - void print() const { - std::cout << "Namespace: " << nmsp.to_string() << "\n"; - std::cout << "Imports:\n"; - for (auto &imp : imports) { - std::cout << " - " << imp.to_string() << "\n"; - } - } - #endif - }; - - template - class parser_t { - public: - virtual bool operator()(ast_ctx_t &ctx, size_t &res_i, ParserT &out) const = 0; - virtual bool simplify(ast_ctx_t &ctx, GlobT &glob, ParserT &val) const = 0; - }; - - - struct ast_ctx_t { + struct parse_ctx_t { public: msg_stack_t &messages; std::vector &tokens; loc_nmsp_t nmsp; - ast_ctx_t &operator=(const ast_ctx_t &other) = delete; - ast_ctx_t(msg_stack_t &messages, std::vector &tokens); + parse_ctx_t &operator=(const parse_ctx_t &other) = delete; + parse_ctx_t(msg_stack_t &messages, std::vector &tokens); }; - bool parse_identifier(ast_ctx_t &ctx, size_t &res_i, located_t &out); - bool parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out); - bool parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, glob_t glob, nmsp_t nmsp); + namespace parse { + bool parse_identifier(parse_ctx_t &ctx, size_t &res_i, located_t &out); + bool parse_nmsp(parse_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out); + bool parse_nmsp_id(parse_ctx_t &ctx, size_t &res_i, std::set imports, nmsp_t nmsp); + } + - class glob_parser_t { - public: - bool operator()(ast_ctx_t &ctx, glob_t &out) const; - }; // 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, parse_struct; diff --git a/include/treeifier/constructs/glob.hh b/include/treeifier/constructs/glob.hh new file mode 100644 index 0000000..16962ad --- /dev/null +++ b/include/treeifier/constructs/glob.hh @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include "lang/common.hh" +#include "utils/message.hh" + +#ifdef PROFILE_debug +#include +#endif + +namespace ppc::tree::constr { + using namespace ppc::lang; + using namespace ppc::messages; + + struct global_t; + + struct definition_t { + virtual std::string name() const = 0; + + virtual bool verify(msg_stack_t &msg_stack, global_t &glob) const { return true; } + virtual bool simplify(global_t &glob) const { return false; } + }; + + struct global_t { + loc_nmsp_t nmsp; + std::vector> defs; + std::vector imports; + + #ifdef PROFILE_debug + void print() const { + std::cout << "Namespace: " << nmsp.to_string() << "\n"; + std::cout << "Imports:\n"; + for (auto &imp : imports) { + std::cout << " - " << imp.to_string() << "\n"; + } + } + #endif + }; +} \ No newline at end of file diff --git a/include/treeifier/parsers/definition.hh b/include/treeifier/parsers/definition.hh new file mode 100644 index 0000000..575da5b --- /dev/null +++ b/include/treeifier/parsers/definition.hh @@ -0,0 +1,13 @@ +#pragma once + +#include "lang/common.hh" +#include "treeifier/tokenizer.hh" +#include "treeifier/constr.hh" +#include "treeifier/constructs/glob.hh" + +namespace ppc::tree::parse { + class definition_parser_t { + public: + virtual bool operator()(parse_ctx_t &ctx, size_t &res_i, constr::definition_t &res) const = 0; + }; +} \ No newline at end of file diff --git a/include/treeifier/parsers/glob.hh b/include/treeifier/parsers/glob.hh new file mode 100644 index 0000000..479b07f --- /dev/null +++ b/include/treeifier/parsers/glob.hh @@ -0,0 +1,16 @@ +#pragma once + +#include "lang/common.hh" +#include "treeifier/tokenizer.hh" +#include "treeifier/constr.hh" +#include "treeifier/constructs/glob.hh" +#include "treeifier/parsers/inspoint.hh" + +namespace ppc::tree::parse { + using namespace constr; + + class glob_parser_t { + public: + bool operator()(parse_ctx_t &ctx, global_t &out) const; + }; +} \ No newline at end of file diff --git a/include/treeifier/constr/helper.hh b/include/treeifier/parsers/helper.hh similarity index 92% rename from include/treeifier/constr/helper.hh rename to include/treeifier/parsers/helper.hh index bfb7186..f0dc831 100644 --- a/include/treeifier/constr/helper.hh +++ b/include/treeifier/parsers/helper.hh @@ -1,15 +1,11 @@ -#include "treeifier/constr.hh" +#pragma once -using namespace ppc; -using namespace ppc::lang; -using namespace ppc::data; -using namespace ppc::tree; -using namespace ppc::tree::constr; +#include "treeifier/constr.hh" -namespace ppc::tree::constr { +namespace ppc::tree::parse { struct helper_t { private: - ast_ctx_t &ctx; + parse_ctx_t &ctx; size_t &res_i; public: @@ -122,7 +118,7 @@ namespace ppc::tree::constr { } } - helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { + helper_t(parse_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { this->i = i; } }; diff --git a/include/treeifier/constr/inspoint.hh b/include/treeifier/parsers/inspoint.hh similarity index 75% rename from include/treeifier/constr/inspoint.hh rename to include/treeifier/parsers/inspoint.hh index 96bb632..de04114 100644 --- a/include/treeifier/constr/inspoint.hh +++ b/include/treeifier/parsers/inspoint.hh @@ -1,8 +1,14 @@ +#pragma once + #include "treeifier/constr.hh" -#include "treeifier/constr/helper.hh" -#include "treeifier/constr/nmsp.hh" +#include "treeifier/parsers/helper.hh" + +#ifdef PROFILE_debug +#include +#endif + +namespace ppc::tree::parse { -namespace ppc::tree::constr { struct named_t { virtual std::string name() = 0; virtual ~named_t() = default; @@ -31,18 +37,13 @@ namespace ppc::tree::constr { return *this; } - bool operator()(ast_ctx_t &ctx, size_t &i, std::unique_ptr &out) const override { + bool operator()(ppc::tree::parse_ctx_t &ctx, size_t &i, std::unique_ptr &out) const override { helper_t h(ctx, i); if (h.ended()) return false; for (std::pair> &pair : parsers) { - ResT res; - - if (pair.second(ctx, i, res)) { - out = std::make_unique(res); - return true; - } + if (pair.second(ctx, i, out)) return true; } return false; diff --git a/src/lsinc.cc b/src/lsinc.cc index 003a3ea..3410a82 100644 --- a/src/lsinc.cc +++ b/src/lsinc.cc @@ -60,10 +60,26 @@ bool get_import(std::string line, fs::path root, fs::path &import) { void get_imports(fs::path file, fs::path include, std::set &res) { static std::set parents = { }; + static std::vector tmp = { }; if (!parents.emplace(file).second) { - throw "Circular dependency encountered."s; + std::stringstream ss; + ss << "Circular dependency encountered ("; + auto it = tmp.rbegin(); + + for (; it != tmp.rend(); it++) { + if (*it == file) break; + ss << *it << "<-"; + } + + ss << *it << ")"; + + parents.clear(); + tmp.clear(); + + throw ss.str(); } + tmp.push_back(file); std::ifstream f(file.string()); if (f.is_open() && !f.eof()) { @@ -80,6 +96,7 @@ void get_imports(fs::path file, fs::path include, std::set &res) { } parents.erase(file); + tmp.pop_back(); } int main(int argc, char **argv) { diff --git a/src/main/main.cc b/src/main/main.cc index aa491e2..ae1d204 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -17,9 +17,10 @@ #endif #include "./opions.hh" -#include "treeifier/constr.hh" #include "treeifier/lexer.hh" #include "treeifier/tokenizer.hh" +#include "treeifier/constructs/glob.hh" +#include "treeifier/parsers/glob.hh" #include "utils/json.hh" #include "utils/strings.hh" #include "utils/threading.hh" @@ -32,7 +33,6 @@ using std::cout; using std::size_t; using namespace ppc; using namespace ppc::tree; -using namespace ppc::tree::constr; void add_flags(options::parser_t &parser) { parser.add_flag({ @@ -162,9 +162,9 @@ int main(int argc, const char *argv[]) { std::ifstream f { file, std::ios_base::in }; if (!f.is_open()) throw message_t::error("The file doesn't exist.", { file }); auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f)); - glob_t glob; - auto ctx = ast_ctx_t(msg_stack, tokens); - glob_parser_t()(ctx, glob); + constr::global_t glob; + auto ctx = parse_ctx_t(msg_stack, tokens); + parse::glob_parser_t()(ctx, glob); #ifdef PROFILE_debug glob.print(); #endif diff --git a/src/treeifier/ast.cc b/src/treeifier/ast.cc index 6063987..029f15c 100644 --- a/src/treeifier/ast.cc +++ b/src/treeifier/ast.cc @@ -2,17 +2,15 @@ #include using namespace ppc; -using namespace ppc::data; using namespace ppc::lang; -using namespace ppc::tree::constr; +using namespace ppc::tree; -// ppc::tree::constr::inspoint_t &ast_ctx_t::group(const std::string &name) { +// ppc::tree::constr::inspoint_t &parse_ctx_t::group(const std::string &name) { // if (groups.find(name) == groups.end()) return groups[name] = {}; // else return groups[name]; // } -ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector &tokens): - messages(messages), tokens(tokens) { +parse_ctx_t::parse_ctx_t(msg_stack_t &messages, std::vector &tokens): messages(messages), tokens(tokens) { // group("$_exp_val") // .add("$_var", parse_exp_var) // .add("$_int", parse_exp_int_lit) diff --git a/src/treeifier/constr.cc b/src/treeifier/constr.cc index ce7ff52..fbc0f58 100644 --- a/src/treeifier/constr.cc +++ b/src/treeifier/constr.cc @@ -1,10 +1,10 @@ #include "treeifier/constr.hh" -#include "treeifier/constr/helper.hh" +#include "treeifier/parsers/helper.hh" #include "lang/common.hh" -using namespace ppc::tree::constr; +using namespace ppc::tree; -bool ppc::tree::constr::parse_identifier(ast_ctx_t &ctx, size_t &res_i, located_t &out) { +bool parse::parse_identifier(parse_ctx_t &ctx, size_t &res_i, located_t &out) { helper_t h(ctx, res_i); if (h.ended()) return false; @@ -16,7 +16,7 @@ bool ppc::tree::constr::parse_identifier(ast_ctx_t &ctx, size_t &res_i, located_ else return false; } -bool ppc::tree::constr::parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out) { +bool parse::parse_nmsp(parse_ctx_t &ctx, size_t &res_i, loc_nmsp_t &out) { helper_t h(ctx, res_i); if (h.ended()) return false; @@ -38,11 +38,11 @@ bool ppc::tree::constr::parse_nmsp(ast_ctx_t &ctx, size_t &res_i, loc_nmsp_t &ou return h.submit(false); } -bool ppc::tree::constr::parse_nmsp_id(ast_ctx_t &ctx, size_t &res_i, glob_t glob, nmsp_t nmsp) { +bool parse::parse_nmsp_id(parse_ctx_t &ctx, size_t &res_i, std::set glob, nmsp_t nmsp) { helper_t h(ctx, res_i); loc_nmsp_t src; if (!h.parse(parse_nmsp, src)) return false; - if (resolve_name(glob.imports, src, nmsp)) return h.submit(false); + if (resolve_name(glob, src, nmsp)) return h.submit(false); else return false; } diff --git a/src/treeifier/constr/glob.cc b/src/treeifier/constr/glob.cc index d150cf2..9e751b0 100644 --- a/src/treeifier/constr/glob.cc +++ b/src/treeifier/constr/glob.cc @@ -1,9 +1,11 @@ #include "treeifier/constr.hh" -#include "treeifier/constr/helper.hh" +#include "treeifier/parsers/helper.hh" +#include "treeifier/parsers/glob.hh" +#include "treeifier/constructs/glob.hh" -using namespace ppc::tree::constr; +using namespace ppc::tree; -bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, glob_t &out) const { +bool parse::glob_parser_t::operator()(parse_ctx_t &ctx, constr::global_t &out) const { size_t res_i = 0; helper_t h(ctx, res_i); out = {}; diff --git a/src/treeifier/lexer.cc b/src/treeifier/lexer.cc index d17352f..358b1d2 100644 --- a/src/treeifier/lexer.cc +++ b/src/treeifier/lexer.cc @@ -26,7 +26,7 @@ struct res_t { }; -static inline bool isoct(char c) { +static inline bool is_oct(char c) { return c >= '0' && c <= '7'; } static inline bool is_any(char c, std::string chars) { @@ -70,7 +70,7 @@ static res_t lexlet_bin(char c, std::vector &tok) { else return lexer_end(token_t::BIN_LITERAL); }; static res_t lexlet_oct(char c, std::vector &tok) { - if (isoct(c)) return lexer_none(); + if (is_oct(c)) return lexer_none(); else if (isdigit(c)) throw message_t::error("An octal literal may only contain octal digits."); else return lexer_end(token_t::OCT_LITERAL); };