diff --git a/.gitignore b/.gitignore index 051d50f..bb6ad7d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,17 +18,20 @@ !src/*/**/*.cc !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 +!deps +!deps/* + !LICENSE !CONTRIBUTING.md !Makefile !README.md -!.gitignore \ No newline at end of file +!.gitignore +!.clang-format \ No newline at end of file diff --git a/Makefile b/Makefile index 9eb6318..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 ############ @@ -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,8 +44,8 @@ export exe=.exe 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 version-build=$(if $(wildcard build.version),$(shell type build.version),0) +export binary = $(bin)/$(output)-$(version-major).$(version-minor)-windows.exe build: version echo ======================== Compiling ========================= @@ -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,8 +74,8 @@ 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 binary = $(bin)/$(output)$(version-major)-linux +# export version-build=$(if $(wildcard build.version),$(shell cat build.version),0) +export binary = $(bin)/$(output)-$(version-major).$(version-minor)-linux build: version echo ======================== Compiling ========================= @@ -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 ======================= diff --git a/src/utils.proj b/deps/lang similarity index 100% rename from src/utils.proj rename to deps/lang 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/src/compiler/treeifier/ast/parsers.cc b/deps/utils similarity index 100% rename from src/compiler/treeifier/ast/parsers.cc rename to deps/utils 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 78b53cd..0000000 --- a/include/compiler/treeifier/ast.hh +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "compiler/treeifier/tokenizer.hh" -#include "utils/data.hh" -#include "lang/common.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); - } - - 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..ed937aa 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,48 @@ 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; + std::string to_string() const; + operator nmsp_t() const { 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; + } + + return false; } } \ 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/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 new file mode 100644 index 0000000..627aed5 --- /dev/null +++ b/include/treeifier/constr.hh @@ -0,0 +1,43 @@ +#pragma once + +#include "utils/message.hh" +#include "lang/common.hh" +#include "treeifier/tokenizer.hh" +#include +#include +#include +#include +#include +#include +#include + +using namespace std::string_literals; + +namespace ppc::tree { + using namespace ppc; + using namespace ppc::lang; + using namespace ppc::messages; + + struct parse_ctx_t { + public: + msg_stack_t &messages; + std::vector &tokens; + loc_nmsp_t nmsp; + + parse_ctx_t &operator=(const parse_ctx_t &other) = delete; + parse_ctx_t(msg_stack_t &messages, std::vector &tokens); + }; + + 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); + } + + + + // 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/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/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/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/compiler/treeifier/ast/helper.hh b/include/treeifier/parsers/helper.hh similarity index 65% rename from include/compiler/treeifier/ast/helper.hh rename to include/treeifier/parsers/helper.hh index 971c562..f0dc831 100644 --- a/include/compiler/treeifier/ast/helper.hh +++ b/include/treeifier/parsers/helper.hh @@ -1,15 +1,11 @@ -#include "compiler/treeifier/ast.hh" +#pragma once -using namespace ppc; -using namespace ppc::lang; -using namespace ppc::data; -using namespace ppc::comp::tree; -using namespace ppc::comp::tree::ast; +#include "treeifier/constr.hh" -namespace ppc::comp::tree::ast { - struct tree_helper_t { +namespace ppc::tree::parse { + struct helper_t { private: - ast_ctx_t &ctx; + parse_ctx_t &ctx; size_t &res_i; public: @@ -104,53 +100,25 @@ namespace ppc::comp::tree::ast { throw_ended(reason); } - 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) { - return ctx.parse(parser, i, out); + template + bool parse(const ParserT &parser, ArgsT &...args) { + return parser(ctx, i, args...); } - 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) { + 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); } - tree_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/parsers/inspoint.hh b/include/treeifier/parsers/inspoint.hh new file mode 100644 index 0000000..de04114 --- /dev/null +++ b/include/treeifier/parsers/inspoint.hh @@ -0,0 +1,52 @@ +#pragma once + +#include "treeifier/constr.hh" +#include "treeifier/parsers/helper.hh" + +#ifdef PROFILE_debug +#include +#endif + +namespace ppc::tree::parse { + + 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()(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) { + if (pair.second(ctx, i, out)) return true; + } + + return false; + } + }; +} \ No newline at end of file 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/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/scripts/common.mak b/scripts/common.mak index c9091f3..ea06da2 100644 --- a/scripts/common.mak +++ b/scripts/common.mak @@ -1,34 +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/lsproj.mak lsproj=$(lsproj) src=$(src) $(lsproj)) +$(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)) +deps=$(shell $(lsdep) --dir=deps $1) +rdeps=$(shell $(lsdep) --dir=deps --rec $1) -ldeps=$(foreach dep,$(call deps,$1),-l$(lib)$(call modoutput,$(dep))) -lrdeps=$(foreach dep,$(call rdeps,$1),-l$(lib)$(call modoutput,$(dep))) +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) @@ -52,7 +37,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 $(headers) +.SECONDEXPANSION: +$(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..c6316fa --- /dev/null +++ b/scripts/ls.mak @@ -0,0 +1,11 @@ +all: $(lsdep) $(lsinc) + +$(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/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/compiler.proj b/src/compiler.proj deleted file mode 100644 index 6fa4f42..0000000 --- a/src/compiler.proj +++ /dev/null @@ -1,2 +0,0 @@ -compiler -utils, lang \ 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 34ff378..0000000 --- a/src/compiler/treeifier/ast/ast.cc +++ /dev/null @@ -1,34 +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 f3a688d..0000000 --- a/src/compiler/treeifier/ast/conv.cc +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include "compiler/treeifier/ast.hh" - -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 700d098..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 2b8021a..0000000 --- a/src/compiler/treeifier/ast/parsers/glob.cc +++ /dev/null @@ -1,69 +0,0 @@ -#include "compiler/treeifier/ast.hh" -#include "compiler/treeifier/ast/helper.hh" -// #include "./type.cc" - -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/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/lang/common.cc b/src/lang/common.cc index bf4bd70..d4cbf5c 100644 --- a/src/lang/common.cc +++ b/src/lang/common.cc @@ -1,9 +1,8 @@ - -#include #include "lang/common.hh" +#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++) { @@ -13,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++) { @@ -24,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]); @@ -35,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]); @@ -47,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); @@ -57,4 +56,3 @@ namespace ppc::lang { return res; } } - diff --git a/src/lang/module.cc b/src/lang/module.cc deleted file mode 100644 index b14c4b1..0000000 --- a/src/lang/module.cc +++ /dev/null @@ -1,88 +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 namespace_name_t &func) { - return { CALL, { .call = new auto(func) }}; -} -statement_t statement_t::stack(int64_t stack) { - return { STACK, { .stack = stack }}; -} -statement_t statement_t::ret() { - return { RETURN }; -} - -bool ppc::lang::resolve_name( - const std::vector &names, const std::set &imports, - const namespace_name_t &name, namespace_name_t &res -) { - for (auto &curr : names) { - if (curr == name) { - res = curr; - return true; - } - } - for (auto &import : imports) { - auto new_name = name; - new_name.insert(new_name.begin(), import.begin(), import.end()); - for (auto &curr : names) { - if (curr == new_name) { - res = curr; - return true; - } - } - } - return false; -} \ No newline at end of file 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 new file mode 100644 index 0000000..3410a82 --- /dev/null +++ b/src/lsinc.cc @@ -0,0 +1,132 @@ +#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, fs::path root, fs::path &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; + 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; + } + + throw "Invalid import syntax."s; +} + +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) { + 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()) { + std::string line; + + while (read_line(f, line)) { + 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); + } + } + } + + parents.erase(file); + tmp.pop_back(); +} + +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: lsinc: " << err << std::endl; + } + + return -1; +} \ No newline at end of file diff --git a/src/lsproj.cc b/src/lsproj.cc deleted file mode 100644 index d32fe3e..0000000 --- a/src/lsproj.cc +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include -#include - -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::size_t cap = 16, n = 0; - std::vector deps { }; - - if (name.length() == 0) { - throw (std::string)"The name of a project may not be empty."; - } - - if (end_ch == -1) { - return project_t { - .output = name, - .deps = deps, - }; - } - - 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."; - } - - 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."; - } - - 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 (std::string)"Incorrect usage. Syntax: [src-dir] [project-name] [output|deps]."; - } - - 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."; - } - - 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 (std::string)"Invalid command given. Available commands: output, deps."; - } - - 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 dd1bfcc..0000000 --- a/src/main.proj +++ /dev/null @@ -1,2 +0,0 @@ -main -utils, compiler \ No newline at end of file diff --git a/src/main/main.cc b/src/main/main.cc index 5a9a16b..ae1d204 100644 --- a/src/main/main.cc +++ b/src/main/main.cc @@ -8,31 +8,31 @@ #define DISABLE_NEWLINE_AUTO_RETURN 0x8 #endif -#include #include +#include #undef ERROR #undef INFO #endif -#include +#include "./opions.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" +#include #include #include -#include -#include "utils/threading.hh" -#include "utils/strings.hh" -#include "utils/json.hh" -#include "compiler/treeifier/lexer.hh" -#include "compiler/treeifier/tokenizer.hh" -#include "compiler/treeifier/ast.hh" -#include "./opions.hh" +#include 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; void add_flags(options::parser_t &parser) { parser.add_flag({ @@ -40,15 +40,15 @@ void add_flags(options::parser_t &parser) { .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"; + cout << "++C compiler\n"; + cout << " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD; +#if WINDOWS + cout << " (Windows)"; +#elif LINUX + cout << " (Linux)"; +#endif + cout << "\n"; + cout << " License: MIT Copyright (C) TopchetoEU\n"; exit(0); } }); @@ -57,10 +57,10 @@ void add_flags(options::parser_t &parser) { .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"; + 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; @@ -89,19 +89,23 @@ void add_flags(options::parser_t &parser) { const size_t padding = 24; const size_t msg_width = 80 - padding; - for (size_t i = 0; i < padding - n; i++) cout << ' '; + 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]; + 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 << ' '; + 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]; + for (int i = 0; i < remainder; i++) + cout << flag.description[len - remainder + i]; } printf("\n"); @@ -129,16 +133,16 @@ void add_flags(options::parser_t &parser) { } 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; @@ -158,9 +162,12 @@ 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; + constr::global_t glob; + auto ctx = parse_ctx_t(msg_stack, tokens); + parse::glob_parser_t()(ctx, glob); + #ifdef PROFILE_debug + glob.print(); + #endif } catch (const messages::message_t &msg) { msg_stack.push(msg); @@ -170,7 +177,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 +185,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/treeifier/ast.cc b/src/treeifier/ast.cc new file mode 100644 index 0000000..029f15c --- /dev/null +++ b/src/treeifier/ast.cc @@ -0,0 +1,34 @@ +#include "treeifier/constr.hh" +#include + +using namespace ppc; +using namespace ppc::lang; +using namespace ppc::tree; + +// 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]; +// } + +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) + // .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.cc b/src/treeifier/constr.cc new file mode 100644 index 0000000..fbc0f58 --- /dev/null +++ b/src/treeifier/constr.cc @@ -0,0 +1,48 @@ +#include "treeifier/constr.hh" +#include "treeifier/parsers/helper.hh" +#include "lang/common.hh" + +using namespace ppc::tree; + +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; + + if (h.curr().is_identifier()) { + out = located_t(h.loc(), h.curr().identifier()); + return h.submit(); + } + else return false; +} + +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; + + 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 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, src, nmsp)) return h.submit(false); + else return false; +} diff --git a/src/treeifier/constr/glob.cc b/src/treeifier/constr/glob.cc new file mode 100644 index 0000000..9e751b0 --- /dev/null +++ b/src/treeifier/constr/glob.cc @@ -0,0 +1,43 @@ +#include "treeifier/constr.hh" +#include "treeifier/parsers/helper.hh" +#include "treeifier/parsers/glob.hh" +#include "treeifier/constructs/glob.hh" + +using namespace ppc::tree; + +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 = {}; + + if (h.ended()) return h.submit(false); + + if (h.curr().is_identifier("namespace")) { + h.advance("Expected a namespace"); + 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))); + } + + if (!h.try_advance()) return h.submit(false); + } + + while (h.curr().is_identifier("import")) { + loc_nmsp_t res; + + 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))); + } + + 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/compiler/treeifier/lexer.cc b/src/treeifier/lexer.cc similarity index 96% rename from src/compiler/treeifier/lexer.cc rename to src/treeifier/lexer.cc index 0127d64..358b1d2 100644 --- a/src/compiler/treeifier/lexer.cc +++ b/src/treeifier/lexer.cc @@ -1,10 +1,10 @@ -#include -#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); @@ -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,10 +70,10 @@ 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); -}; +}; 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/treeifier/operators.cc similarity index 89% rename from src/compiler/treeifier/operators.cc rename to src/treeifier/operators.cc index b03bd90..d3fc66a 100644 --- a/src/compiler/treeifier/operators.cc +++ b/src/treeifier/operators.cc @@ -1,8 +1,8 @@ +#include "treeifier/tokenizer.hh" #include -#include "compiler/treeifier/tokenizer.hh" -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 e603d86..b03b009 100644 --- a/src/compiler/treeifier/tokenizer.cc +++ b/src/treeifier/tokenizer.cc @@ -1,11 +1,11 @@ -#include +#include "treeifier/lexer.hh" +#include "treeifier/tokenizer.hh" #include -#include "compiler/treeifier/tokenizer.hh" -#include "compiler/treeifier/lexer.hh" +#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) { 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