This commit is contained in:
TopchetoEU 2022-10-04 23:45:08 +03:00
parent 9890630b79
commit 0a68529c3b
12 changed files with 103 additions and 38 deletions

1
.gitignore vendored
View File

@ -23,6 +23,7 @@
!scripts !scripts
!scripts/common.mak !scripts/common.mak
!scripts/lsproj.mak
!scripts/install.bat !scripts/install.bat
!scripts/uninstall.bat !scripts/uninstall.bat

View File

@ -1,4 +1,4 @@
export MAKEFLAGS += --silent -r export MAKEFLAGS += --silent -r -j
export flags=-std=c++17 -Wall -Wno-main -Wno-trigraphs -Wno-missing-braces -Wno-stringop-overflow export flags=-std=c++17 -Wall -Wno-main -Wno-trigraphs -Wno-missing-braces -Wno-stringop-overflow
export ldflags=-L$(bin)/$(profile) export ldflags=-L$(bin)/$(profile)
export lib=ppc$(version-major)- export lib=ppc$(version-major)-
@ -51,7 +51,7 @@ build: version
make -f scripts/common.mak make -f scripts/common.mak
if exist "$(subst /,\,$(bin)\$(output).exe)" del "$(subst /,\,$(bin)\$(output).exe)" if exist "$(subst /,\,$(bin)\$(output).exe)" del "$(subst /,\,$(bin)\$(output).exe)"
mklink /H "$(subst /,\,$(bin)\$(output).exe)" "$(subst /,\,$(binary))" > NUL mklink /H "$(subst /,\,$(bin)\$(output).exe)" "$(subst /,\,$(binary))" > NUL
echo Done!
clear: clear:
if exist $(subst /,\,$(oldbin)) rmdir /s /q $(subst /,\,$(oldbin)) if exist $(subst /,\,$(oldbin)) rmdir /s /q $(subst /,\,$(oldbin))

View File

@ -10,6 +10,7 @@
using namespace std::string_literals; using namespace std::string_literals;
using namespace ppc; using namespace ppc;
using namespace ppc::lang;
using namespace ppc::messages; using namespace ppc::messages;
namespace ppc::comp::tree::ast { namespace ppc::comp::tree::ast {
@ -42,6 +43,8 @@ namespace ppc::comp::tree::ast {
public: public:
msg_stack_t &messages; msg_stack_t &messages;
std::vector<token_t> &tokens; std::vector<token_t> &tokens;
std::set<lang::namespace_name_t> imports;
located_t<namespace_name_t> nmsp;
void add_parser(std::string name, parser_t &parser); void add_parser(std::string name, parser_t &parser);
void add_parser(std::string name, group_parser_t &parser); void add_parser(std::string name, group_parser_t &parser);
@ -57,10 +60,7 @@ namespace ppc::comp::tree::ast {
}; };
class parser_t { class parser_t {
private:
std::string _name;
public: public:
const std::string &name() { return _name; }
virtual bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const = 0; virtual bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const = 0;
bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
return parse(ctx, i, out); return parse(ctx, i, out);

View File

@ -5,14 +5,19 @@ namespace ppc::comp::tree::ast {
private: private:
ast_ctx_t &ctx; ast_ctx_t &ctx;
size_t &res_i; size_t &res_i;
size_t i;
void throw_ended() { void throw_ended() {
if (ended()) throw messages::message_t(message_t::ERROR, "Unexpected end.", loc()); if (ended()) throw messages::message_t(message_t::ERROR, "Unexpected end.", loc());
} }
void throw_ended(const std::string &reason) {
if (ended()) throw messages::message_t(message_t::ERROR, "Unexpected end: " + reason, loc());
}
public: public:
void submit() { size_t i;
bool submit() {
res_i = i; res_i = i;
return true;
} }
bool ended() { bool ended() {
@ -83,6 +88,11 @@ namespace ppc::comp::tree::ast {
i++; i++;
throw_ended(); throw_ended();
} }
void advance(const std::string &reason) {
throw_ended(reason);
i++;
throw_ended(reason);
}
tree_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) { tree_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) {
this->i = i; this->i = i;

View File

@ -8,10 +8,9 @@ namespace ppc::lang {
struct located_t : T { struct located_t : T {
location_t location; location_t location;
template <class ...Args> located_t(location_t loc, const T &val): T(val), location(loc) { }
located_t(location_t loc, Args ...args): T(args...), location(loc) { } located_t(const T &val): T(val), location(location_t::NONE) { }
template <class ...Args> located_t() { }
located_t(Args ...args): T(args...), location(location_t::NONE) { }
}; };
struct namespace_name_t : public std::vector<std::string> { struct namespace_name_t : public std::vector<std::string> {

View File

@ -17,7 +17,7 @@ namespace ppc::messages {
std::string content; std::string content;
location_t location; location_t location;
message_t(level_t level, std::string content, location_t loc = location_t::NONE) : message_t(level_t level, const std::string &content, location_t loc = location_t::NONE) :
level(level), level(level),
content(content), content(content),
location(loc) { } location(loc) { }
@ -25,6 +25,8 @@ namespace ppc::messages {
std::string to_string() const; std::string to_string() const;
bool is_severe() const; bool is_severe() const;
static message_t error(const std::string &message, location_t loc = location_t::NONE) { return message_t(ERROR, message, loc); }
}; };
struct msg_stack_t { struct msg_stack_t {

View File

@ -1,14 +1,16 @@
export lsproj = $(bin)/lsproj$(exe) export lsproj = $(bin)/lsproj$(exe)
export flags += "-I$(inc)" -D$(OS) -DPPC_VERSION_MAJOR=$(version-major) -DPPC_VERSION_MINOR=$(version-minor) -DPPC_VERSION_BUILD=$(version-build) export flags += "-I$(inc)" -D$(OS) -DPPC_VERSION_MAJOR=$(version-major) -DPPC_VERSION_MINOR=$(version-minor) -DPPC_VERSION_BUILD=$(version-build)
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) 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))) uniq=$(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
modoutput=$(shell ./$(lsproj) $(src) $1 output) modoutput=$(shell ./$(lsproj) $(src) $1 output)
deps=$(strip \ deps=$(strip \
$(foreach dep, $(shell ./$(lsproj) $(src) $1 deps),\ $(foreach dep, $(shell ./$(lsproj) $(src) $1 deps),\
$(if $(wildcard src/$(dep)),\ $(if $(wildcard src/$(dep)), $(dep),\
$(dep),\
$(error The module '$(dep)' (dependency of '$1') doesn't exist)\ $(error The module '$(dep)' (dependency of '$1') doesn't exist)\
)\ )\
)\ )\
@ -29,15 +31,14 @@ lrdeps=$(foreach dep,$(call rdeps,$1),-l$(lib)$(call modoutput,$(dep)))
modules = $(patsubst $(src)/%/,$(bin)/lib$(lib)%$(so),$(filter-out $(src)/$(mainmodule)/,$(wildcard $(src)/*/))) modules = $(patsubst $(src)/%/,$(bin)/lib$(lib)%$(so),$(filter-out $(src)/$(mainmodule)/,$(wildcard $(src)/*/)))
sources = $(call rwildcard,$(src)/$1,*.cc) sources = $(call rwildcard,$(src)/$1,*.cc)
headers = $(call rwildcard,$(inc),*.h) headers = $(call rwildcard,$(inc),*.h)
binaries = $(patsubst $(src)/%.cc,$(bin)/%.o,$(call sources,$1)) binaries = $(patsubst $(src)/%.cc,$(bin)/tmp/%.o,$(call sources,$1))
ifneq ($(nolsproj),yes) ifneq ($(nolsproj),yes)
$(shell make -f scripts/lsproj.mak $(lsproj)) $(shell make -f scripts/lsproj.mak lsproj=$(lsproj) src=$(src) $(lsproj))
endif endif
.PHONY: build .PHONY: build
.PRECIOUS: $(bin)/%.o .PRECIOUS: $(bin)/tmp/%.o
build: $(binary) build: $(binary)
@ -53,7 +54,7 @@ $(bin)/lib$(lib)%$(so): $$(call frdeps,$$*) $$(call binaries,$$*)
echo Compiling library '$(notdir $@)'... echo Compiling library '$(notdir $@)'...
$(CXX) -shared -fPIC $(flags) $(call binaries,$*) -o $@ $(ldflags) $(call ldeps,$*) -L$(bin) "-I$(inc)" $(CXX) -shared -fPIC $(flags) $(call binaries,$*) -o $@ $(ldflags) $(call ldeps,$*) -L$(bin) "-I$(inc)"
$(bin)/%.o: $(src)/%.cc $(headers) $(bin)/tmp/%.o: $(src)/%.cc $(headers)
echo - Compiling '$*.cc'... echo - Compiling '$*.cc'...
$(call mkdir,$(dir $@)) $(call mkdir,$(dir $@))
$(CXX) -fPIC -c $(flags) $< -o $@ $(CXX) -fPIC -c $(flags) $< -o $@

View File

@ -1,9 +1,59 @@
#include "compiler/treeifier/ast.hh" #include "compiler/treeifier/ast.hh"
#include "compiler/treeifier/ast/helper.hh"
namespace ppc::comp::tree::ast { namespace ppc::comp::tree::ast {
class glob_parser_t : public parser_t { class glob_parser_t : public parser_t {
bool parse_nmsp(ast_ctx_t &ctx, size_t &res_i, located_t<namespace_name_t> &out) const {
tree_helper_t h(ctx, res_i);
located_t<namespace_name_t> res;
while (true) {
auto &curr = h.curr();
if (h.ended() || !curr.is_identifier()) return false;
else res.push_back(curr.identifier());
if (!h.try_advance() || !h.curr().is_operator(operator_t::DOUBLE_COLON)) {
out = res;
return h.submit();
}
}
}
bool parse_nmsp_def(ast_ctx_t &ctx, size_t &res_i) const {
tree_helper_t h(ctx, res_i);
if (h.ended()) return true;
if (h.curr().is_identifier("namespace")) {
h.advance("Expected a namespace name.");
if (!parse_nmsp(ctx, h.i, ctx.nmsp)) throw message_t::error("Expected a namespace name.", h.loc());
return h.submit();
}
else return false;
}
bool parse_import(ast_ctx_t &ctx, size_t &res_i) const {
tree_helper_t h(ctx, res_i);
if (h.ended()) return true;
if (h.curr().is_identifier("import")) {
h.advance("Expected a namespace name.");
located_t<namespace_name_t> name;
if (!parse_nmsp(ctx, h.i, name)) throw message_t::error("Expected a namespace name.", h.loc());
if (!ctx.imports.emplace(name).second) {
throw message_t::error("The namespace '" + name.to_string() + "' is already imported.", h.loc());
}
return h.submit();
}
else return false;
}
bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const { bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const {
return false; tree_helper_t h(ctx, res_i);
if (h.ended()) return true;
parse_nmsp_def(ctx, h.i);
while (parse_import(ctx, h.i));
return true;
} }
}; };

View File

@ -41,12 +41,14 @@ bool group_parser_t::parse(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
try { try {
return h.parse(*parser, out); return h.parse(*parser, out);
} }
catch (std::string) { catch (const message_t &err) {
ctx.messages.push(err);
return false; return false;
} }
} }
}
return false;
}
group_parser_t &group_parser_t::add(parser_t &parser) { group_parser_t &group_parser_t::add(parser_t &parser) {
parsers.push_back(&parser); parsers.push_back(&parser);

View File

@ -52,7 +52,7 @@ static std::vector<char> parse_string(msg_stack_t &msg_stack, bool is_char, lex:
if (is_char) throw message_t(message_t::ERROR, "Unterminated char literal.", token.location); if (is_char) throw message_t(message_t::ERROR, "Unterminated char literal.", token.location);
else throw message_t(message_t::ERROR, "Unterminated string literal.", token.location); else throw message_t(message_t::ERROR, "Unterminated string literal.", token.location);
} }
static tok::token_t parse_int(msg_stack_t &msg_stack, lex::token_t token) { static token_t parse_int(msg_stack_t &msg_stack, lex::token_t token) {
enum radix_t { enum radix_t {
BINARY, BINARY,
OCTAL, OCTAL,
@ -119,9 +119,9 @@ static tok::token_t parse_int(msg_stack_t &msg_stack, lex::token_t token) {
} }
} }
return tok::token_t(res, token.location); return token_t(res, token.location);
} }
static tok::token_t parse_float(msg_stack_t &msg_stack, lex::token_t token) { static token_t parse_float(msg_stack_t &msg_stack, lex::token_t token) {
double whole = 0, fract = 0; double whole = 0, fract = 0;
char c; char c;
@ -143,16 +143,16 @@ static tok::token_t parse_float(msg_stack_t &msg_stack, lex::token_t token) {
} }
} }
return tok::token_t(whole + fract, token.location); return token_t(whole + fract, token.location);
} }
tok::token_t tok::token_t::parse(messages::msg_stack_t &msg_stack, lex::token_t in) { token_t token_t::parse(messages::msg_stack_t &msg_stack, lex::token_t in) {
switch (in.type) { switch (in.type) {
case lex::token_t::IDENTIFIER: case lex::token_t::IDENTIFIER:
return tok::token_t(in.data, in.location); return token_t(in.data, in.location);
case lex::token_t::OPERATOR: case lex::token_t::OPERATOR:
try { try {
auto op = tok::operator_find(in.data); auto op = operator_find(in.data);
return token_t(op, in.location); return token_t(op, in.location);
} }
catch (std::string &err) { catch (std::string &err) {
@ -176,11 +176,11 @@ tok::token_t tok::token_t::parse(messages::msg_stack_t &msg_stack, lex::token_t
throw message_t(message_t::ERROR, "Token type not recognised.", in.location); throw message_t(message_t::ERROR, "Token type not recognised.", in.location);
} }
} }
std::vector<tok::token_t> tok::token_t::parse_many(messages::msg_stack_t &msg_stack, std::vector<lex::token_t> tokens) { std::vector<token_t> token_t::parse_many(messages::msg_stack_t &msg_stack, std::vector<lex::token_t> tokens) {
std::vector<tok::token_t> res; std::vector<token_t> res;
for (auto &tok : tokens) { for (auto &tok : tokens) {
res.push_back(tok::token_t::parse(msg_stack, tok)); res.push_back(token_t::parse(msg_stack, tok));
} }
return res; return res;

View File

@ -4,14 +4,14 @@ using namespace ppc;
bool version_t::operator==(version_t other) const { bool version_t::operator==(version_t other) const {
bool major_same = major == other.major; bool major_same = major == other.major;
bool minor_same = minor == -1 || other.minor == -1 || minor == other.minor; bool minor_same = minor == -1u || other.minor == -1 || minor == other.minor;
bool revision_same = revision == -1 || other.revision == -1 || revision == other.revision; bool revision_same = revision == -1u || other.revision == -1u || revision == other.revision;
return major_same && minor_same && revision_same; return major_same && minor_same && revision_same;
} }
bool version_t::is_compliant(version_t other) const { bool version_t::is_compliant(version_t other) const {
bool major_compliant = major == other.major; bool major_compliant = major == other.major;
bool minor_compliant = minor == -1 || other.minor == -1 || minor <= other.minor; bool minor_compliant = minor == -1u || other.minor == -1u || minor <= other.minor;
return major_compliant && minor_compliant; return major_compliant && minor_compliant;
} }

View File

@ -152,11 +152,11 @@ int main(int argc, const char *argv[]) {
for (const auto &file : files) { for (const auto &file : files) {
std::ifstream f { file, std::ios_base::in }; std::ifstream f { file, std::ios_base::in };
try { try {
auto res = tok::token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f)); auto res = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f));
for (auto tok : res) { for (auto tok : res) {
if (tok.is_identifier()) std::cout << "Identifier: \t" << tok.identifier(); if (tok.is_identifier()) std::cout << "Identifier: \t" << tok.identifier();
if (tok.is_operator()) std::cout << "Operator: \t" << tok::operator_stringify(tok._operator()); if (tok.is_operator()) std::cout << "Operator: \t" << operator_stringify(tok._operator());
if (tok.is_float_lit()) std::cout << "Float: \t" << tok.float_lit(); if (tok.is_float_lit()) std::cout << "Float: \t" << tok.float_lit();
if (tok.is_int_lit()) std::cout << "Int: \t" << tok.int_lit(); if (tok.is_int_lit()) std::cout << "Int: \t" << tok.int_lit();
if (tok.is_char_lit()) std::cout << "Char: \t" << tok.char_lit(); if (tok.is_char_lit()) std::cout << "Char: \t" << tok.char_lit();