a lot.
This commit is contained in:
parent
9890630b79
commit
0a68529c3b
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||||
|
|
||||||
|
4
Makefile
4
Makefile
@ -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))
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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> {
|
||||||
|
@ -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 {
|
||||||
|
@ -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 $@
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user