feat: add namespace and import parsing

This commit is contained in:
TopchetoEU 2022-10-09 14:18:38 +03:00
parent 0a68529c3b
commit ee6c29bb7d
25 changed files with 655 additions and 334 deletions

2
.gitignore vendored
View File

@ -18,7 +18,7 @@
!src/*/**/*.cc
!src/*/**/*.h
!src/*/**/*.hh
!src/*/proj.txt
!src/*.proj
!src/lsproj.cc
!scripts

View File

@ -17,54 +17,71 @@ namespace ppc::comp::tree::ast {
class parser_t;
class group_parser_t;
extern const parser_t &glob_parser;
extern const parser_t &identifier_parser;
extern const parser_t &nmsp_parser;
struct ast_ctx_t {
private:
using named_parser_t = std::pair<std::string, parser_t*>;
struct parser_proxy_t {
private:
ast_ctx_t &parent;
ast_ctx_t *parent;
public:
parser_t &operator[](const std::string &name) const;
parser_proxy_t(ast_ctx_t &parent): parent(parent) { }
const parser_t &operator[](const std::string &name) const;
parser_proxy_t(ast_ctx_t *parent): parent(parent) { }
};
struct group_proxy_t {
private:
ast_ctx_t &parent;
ast_ctx_t *parent;
public:
group_parser_t &operator[](const std::string &name) const;
group_proxy_t(ast_ctx_t &parent): parent(parent) { }
const group_parser_t &operator[](const std::string &name) const;
group_proxy_t(ast_ctx_t *parent): parent(parent) { }
};
std::unordered_map<std::string, parser_t*> parsers;
std::set<parser_t*> groups;
std::unordered_map<std::string, const parser_t*> parsers;
std::set<const parser_t*> groups;
public:
msg_stack_t &messages;
std::vector<token_t> &tokens;
std::set<lang::namespace_name_t> imports;
located_t<namespace_name_t> nmsp;
std::set<loc_namespace_name_t> imports;
loc_namespace_name_t nmsp;
void add_parser(std::string name, parser_t &parser);
void add_parser(std::string name, group_parser_t &parser);
void add_parser(const parser_t &parser);
void add_parser(const group_parser_t &parser);
const parser_proxy_t parser;
const group_proxy_t group;
ast_ctx_t(msg_stack_t &messages, std::vector<token_t> tokens):
ast_ctx_t &init() {
add_parser(glob_parser);
return *this;
}
static bool parse(msg_stack_t &messages, std::vector<token_t> &tokens, data::map_t &out);
ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens):
messages(messages),
tokens(tokens),
parser(*this),
group(*this) { }
parser(this),
group(this) { }
};
class parser_t {
public:
private:
std::string _name;
protected:
virtual bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const = 0;
public:
const std::string &name() const { return _name; }
bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
data::map_t res;
out["$_name"] = _name;
return parse(ctx, i, out);
}
parser_t(const std::string &name): _name(name) { }
};
class group_parser_t : public parser_t {
@ -78,7 +95,14 @@ namespace ppc::comp::tree::ast {
bool parse(ast_ctx_t &ctx, size_t &i, data::map_t &out) const;
};
extern const parser_t &glob_parser;
namespace conv {
data::map_t identifier_to_map(const located_t<std::string> &loc);
located_t<std::string> map_to_identifier(const data::map_t &map);
const group_parser_t &get_group(std::string name);
data::map_t loc_to_map(const location_t &loc);
location_t map_to_loc(const data::map_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);
}
}

View File

@ -1,5 +1,11 @@
#include "compiler/treeifier/ast.hh"
using namespace ppc;
using namespace ppc::lang;
using namespace ppc::data;
using namespace ppc::comp::tree;
using namespace ppc::comp::tree::ast;
namespace ppc::comp::tree::ast {
struct tree_helper_t {
private:
@ -15,20 +21,6 @@ namespace ppc::comp::tree::ast {
public:
size_t i;
bool submit() {
res_i = i;
return true;
}
bool ended() {
return i == ctx.tokens.size();
}
token_t &curr() {
throw_ended();
return ctx.tokens[i];
}
location_t next_loc(size_t n = 1) {
location_t res = loc();
res.start += res.length;
@ -56,26 +48,22 @@ namespace ppc::comp::tree::ast {
else return ctx.tokens[res_i].location.intersect(loc());
}
bool parse(const parser_t &parser, data::map_t &out) {
return parser(ctx, i, out);
void err(std::string message) {
throw message_t::error(message, loc());
}
bool try_parse(const parser_t &parser, data::map_t &out, bool silent = true) {
try {
return parser(ctx, i, out);
bool submit(bool inc_i = true) {
res_i = (i += inc_i);
return true;
}
catch (messages::message_t msg) {
if (!silent) ctx.messages.push(msg);
return false;
}
}
bool try_parse(const parser_t &parser, data::map_t &out, message_t &err) {
try {
return parser(ctx, i, out);
}
catch (messages::message_t msg) {
err = msg;
return false;
bool ended() {
return i == ctx.tokens.size();
}
token_t &curr() {
throw_ended();
return ctx.tokens[i];
}
bool try_advance() {
@ -94,6 +82,48 @@ namespace ppc::comp::tree::ast {
throw_ended(reason);
}
bool push_parse(const parser_t &parser, data::array_t &out) {
data::map_t res;
if (parser(ctx, i, res)) {
out.push(res);
return true;
}
else return false;
}
bool parse(const parser_t &parser, data::map_t &out) {
return parser(ctx, i, out);
}
void force_push_parse(const parser_t &parser, std::string message, data::array_t &out) {
advance(message);
bool success;
try {
success = push_parse(parser, out);
}
catch (const message_t &msg) {
ctx.messages.push(msg);
success = false;
}
if (!success) err(message);
}
void force_parse(const parser_t &parser, std::string message, data::map_t &out) {
advance(message);
bool success;
try {
success = parse(parser, out);
}
catch (const message_t &msg) {
ctx.messages.push(msg);
success = false;
}
if (!success) err(message);
}
tree_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) {
this->i = i;
}

View File

@ -19,15 +19,31 @@ namespace ppc::lang {
bool operator ==(const namespace_name_t &other) const;
bool operator !=(const namespace_name_t &other) const;
operator std::string() const { return to_string(); }
std::string to_string() const;
namespace_name_t() { }
namespace_name_t(std::initializer_list<std::string> segments): base(segments.begin(), segments.end()) { }
};
struct loc_namespace_name_t : public std::vector<located_t<std::string>> {
using base = std::vector<located_t<std::string>>;
bool operator ==(const loc_namespace_name_t &other) const;
bool operator !=(const loc_namespace_name_t &other) const;
namespace_name_t 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<located_t<std::string>> 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 { };
messages::msg_stack_t ms;
return is_identifier_valid(ms, { }, name);
}
}

View File

@ -45,22 +45,26 @@ namespace ppc::data {
bool string(string_t &out) const;
bool boolean(bool_t &out) const;
const array_t &array() const;
const map_t &map() const;
array_t &array() const;
map_t &map() const;
number_t number() const;
const string_t &string() const;
string_t &string() const;
bool_t boolean() const;
// value_t &operator=(const value_t &other);
value_t &operator=(const value_t &other);
~value_t();
value_t();
value_t(const array_t &val);
value_t(const map_t &val);
value_t(std::initializer_list<std::pair<std::string, value_t>> map);
value_t(number_t val);
value_t(const string_t &val);
value_t(bool_t val);
value_t(const value_t &other);
static value_t mk_arr();
static value_t mk_map();
};
@ -69,17 +73,33 @@ namespace ppc::data {
std::unordered_map<std::string, value_t> values;
public:
value_t &operator [](std::string name){
if (values.find(name) == values.end()) {
values.emplace(name, value_t());
auto res = values.find(name);
if (res == values.end()) {
res = values.emplace(name, value_t()).first;
}
return res->second;
}
const value_t &operator [](std::string name) const {
auto res = values.find(name);
if (res == values.end()) throw "The map doesn't contain a key '" + name + "'.";
return res->second;
}
return values[name];
bool has(std::string key) const {
return values.find(key) != values.end();
}
std::size_t size() const { return values.size(); }
auto begin() const { return values.begin(); }
auto end() const { return values.end(); }
map_t() { }
map_t(std::initializer_list<std::pair<std::string, value_t>> vals) {
for (const auto &pair : vals) {
values.insert(pair);
}
}
};
class array_t {
@ -87,9 +107,10 @@ namespace ppc::data {
std::vector<value_t> values;
public:
value_t &operator [](std::size_t i) { return values[i]; }
const value_t &operator [](std::size_t i) const { return values[i]; }
auto begin() { return values.begin(); }
auto end() { return values.end(); }
auto begin() const { return values.begin(); }
auto end() const { return values.end(); }
void push(const value_t &val) { values.push_back(val); }
void insert(const value_t &val, std::size_t i = 0) { values.insert(begin() + i, val); }
@ -97,5 +118,9 @@ namespace ppc::data {
void remove(std::size_t i = 0) { values.erase(begin() + i); }
std::size_t size() const { return values.size(); }
array_t() { }
array_t(const std::vector<value_t> &val): values(val) { }
array_t(std::initializer_list<value_t> val): values(val) { }
};
}

View File

@ -12,6 +12,7 @@ namespace ppc {
std::size_t code_start;
std::string filename;
operator std::string() const { return to_string(); }
std::string to_string() const;
location_t intersect(location_t other) const;

View File

@ -23,6 +23,8 @@ namespace ppc::messages {
location(loc) { }
message_t() : message_t(DEBUG, "") { }
operator std::string() const { return to_string(); }
std::string to_string() const;
bool is_severe() const;
@ -37,6 +39,7 @@ namespace ppc::messages {
inline auto end() { return messages.end(); }
void push(const message_t &msg) { messages.push_back(msg); }
const message_t &peek() { return messages.back(); }
void clear() { messages.clear(); }
bool is_failed() const;

View File

@ -1,6 +1,8 @@
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)
$(shell make -f scripts/lsproj.mak lsproj=$(lsproj) src=$(src) $(lsproj))
rwildcard=$(foreach d, $(wildcard $(1:=/*)),\
$(call rwildcard,$d,$2)\
$(filter $(subst *,%,$2),$d)\
@ -30,13 +32,9 @@ lrdeps=$(foreach dep,$(call rdeps,$1),-l$(lib)$(call modoutput,$(dep)))
modules = $(patsubst $(src)/%/,$(bin)/lib$(lib)%$(so),$(filter-out $(src)/$(mainmodule)/,$(wildcard $(src)/*/)))
sources = $(call rwildcard,$(src)/$1,*.cc)
headers = $(call rwildcard,$(inc),*.h)
headers = $(call rwildcard,$(inc),*.hh)
binaries = $(patsubst $(src)/%.cc,$(bin)/tmp/%.o,$(call sources,$1))
ifneq ($(nolsproj),yes)
$(shell make -f scripts/lsproj.mak lsproj=$(lsproj) src=$(src) $(lsproj))
endif
.PHONY: build
.PRECIOUS: $(bin)/tmp/%.o

View File

@ -3,25 +3,44 @@
namespace ppc::comp::tree::ast {
std::unordered_map<std::string, group_parser_t> parsers;
parser_t &ast_ctx_t::parser_proxy_t::operator[](const std::string &name) const {
auto it = parent.parsers.find(name);
if (it == parent.parsers.end()) throw "The parser '" + name + "' doesn't exist.";
const parser_t &ast_ctx_t::parser_proxy_t::operator[](const std::string &name) const {
auto it = parent->parsers.find(name);
if (it == parent->parsers.end()) throw "The parser '" + name + "' doesn't exist.";
return *it->second;
}
group_parser_t &ast_ctx_t::group_proxy_t::operator[](const std::string &name) const {
parser_t *p = &parent.parser[name];
if (parent.groups.find(p) == parent.groups.end()) throw "A parser '" + name + "' exists, but isn't a group.";
return *(group_parser_t*)p;
const group_parser_t &ast_ctx_t::group_proxy_t::operator[](const std::string &name) const {
auto p = &parent->parser[name];
if (parent->groups.find(p) == parent->groups.end()) throw "A parser '" + name + "' exists, but isn't a group.";
return *(const group_parser_t*)p;
}
void ast_ctx_t::add_parser(std::string name, parser_t &parser) {
if (parsers.find(name) != parsers.end()) throw "The parser '" + name + "' already exists.";
parsers[name] = &parser;
void ast_ctx_t::add_parser(const parser_t &parser) {
if (parsers.find(parser.name()) != parsers.end()) throw "The parser '" + parser.name() + "' already exists.";
parsers[parser.name()] = &parser;
}
void ast_ctx_t::add_parser(std::string name, group_parser_t &parser) {
if (parsers.find(name) != parsers.end()) throw "The parser '" + name + "' already exists.";
parsers[name] = &parser;
void ast_ctx_t::add_parser(const group_parser_t &parser) {
if (parsers.find(parser.name()) != parsers.end()) throw "The parser '" + parser.name() + "' already exists.";
parsers[parser.name()] = &parser;
groups.emplace(&parser);
}
bool ast_ctx_t::parse(msg_stack_t &messages, std::vector<token_t> &tokens, data::map_t &out) {
ast_ctx_t ctx(messages, tokens);
ctx.init();
data::map_t res;
size_t i = 0;
try {
if (glob_parser(ctx, i, out)) {
out = res;
return true;
}
else return false;
}
catch (const message_t &msg) {
messages.push(msg);
return false;
}
}
}

View File

@ -0,0 +1,80 @@
#include "compiler/treeifier/ast.hh"
namespace ppc::comp::tree::ast::conv {
data::map_t identifier_to_map(const located_t<std::string> &loc) {
return {
{ "location", conv::loc_to_map(loc.location) },
{ "content", loc },
{ "$_name", identifier_parser.name() },
};
}
located_t<std::string> map_to_identifier(const data::map_t &map) {
return { conv::map_to_loc(map["location"].map()), map["content"].string() };
}
data::map_t loc_to_map(const location_t &loc) {
data::map_t res = {
{ "$_name", "$_loc" },
};
if (loc.filename != "") res["filename"] = loc.filename;
if (loc.start != -1u) res["start"] = (float)loc.start;
if (loc.code_start != -1u) res["code_start"] = (float)loc.code_start;
if (loc.length != -1u) res["length"] = (float)loc.length;
return res;
}
location_t map_to_loc(const data::map_t &map) {
location_t res;
if (map.has("filename")) {
if (map["filename"].is_string()) res.filename = map["filename"].string();
else throw "Expected key 'filename' to be a string.";
}
if (map.has("start")) {
if (map["start"].is_number()) res.start = (size_t)map["start"].number();
else throw "Expected key 'start' to be a number.";
}
if (map.has("length")) {
if (map["length"].is_number()) res.length = (size_t)map["length"].number();
else throw "Expected key 'length' to be a number.";
}
if (map.has("code_start")) {
if (map["code_start"].is_number()) res.code_start = (size_t)map["code_start"].number();
else throw "Expected key 'code_start' to be a number.";
}
return res;
}
data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp) {
data::map_t res;
auto arr = (res["content"] = data::array_t()).array();
for (const auto &segment : nmsp) {
arr.push({
{ "location", loc_to_map(segment.location) },
{ "content", segment },
{ "$_name", nmsp_parser.name() },
});
}
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;
}
}

View File

@ -0,0 +1,65 @@
#include "compiler/treeifier/ast.hh"
#include "compiler/treeifier/ast/helper.hh"
using namespace ppc::comp::tree::ast;
class nmsp_def_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) const {
tree_helper_t h(ctx, res_i);
if (h.ended()) return false;
if (!h.curr().is_identifier("namespace")) return false;
h.force_parse(nmsp_parser, "Expected a namespace.", res);
if (!h.curr().is_operator(operator_t::SEMICOLON)) h.err("Expected a semicolon.");
return h.submit(true);
}
public: nmsp_def_parser_t(): parser_t("$_nmsp_def") { }
};
class import_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) const {
tree_helper_t h(ctx, res_i);
if (h.ended()) return false;
if (!h.curr().is_identifier("import")) return false;
h.force_parse(nmsp_parser, "Expected a namespace.", res);
if (!h.curr().is_operator(operator_t::SEMICOLON)) h.err("Expected a semicolon.");
return h.submit(true);
}
public: import_parser_t(): parser_t("$_import") { }
};
const parser_t &import_parser = import_parser_t();
const parser_t &nmsp_def_parser = nmsp_def_parser_t();
class glob_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) const {
tree_helper_t h(ctx, res_i);
if (h.ended()) return true;
h.parse(nmsp_def_parser, (out["namespace"] = map_t()).map());
ctx.nmsp = conv::map_to_nmsp(out["namespace"].map());
auto imports = (out["imports"] = array_t()).array();
while (true) {
map_t map;
imports.push(map);
if (!h.parse(import_parser, map)) break;
auto nmsp = conv::map_to_nmsp(map);
if (!ctx.imports.emplace(nmsp).second) h.err("The namespace '" + nmsp.to_string() + "' is already imported.");
}
if (!h.ended()) h.err("Invalid token.");
return h.submit();
}
public:
glob_parser_t(): parser_t("$_glob") { }
};
const parser_t &ppc::comp::tree::ast::glob_parser = glob_parser_t();

View File

@ -0,0 +1,21 @@
#include "compiler/treeifier/ast/helper.hh"
class identifier_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, map_t &out) const {
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;
}
public: identifier_parser_t(): parser_t("$_identifier") { }
};
const parser_t &ppc::comp::tree::ast::identifier_parser = identifier_parser_t();

View File

@ -0,0 +1,26 @@
#include "compiler/treeifier/ast/helper.hh"
class nmsp_parser_t : public parser_t {
bool parse(ast_ctx_t &ctx, size_t &res_i, map_t &out) const {
tree_helper_t h(ctx, res_i);
if (h.ended()) return false;
auto &arr = (out["content"] = array_t()).array();
if (!h.push_parse(identifier_parser, arr)) return false;
while (true) {
if (h.ended()) break;
if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break;
h.force_push_parse(identifier_parser, "Expected an identifier.", arr);
}
out["location"] = conv::loc_to_map(h.res_loc());
return h.submit(false);
}
public: nmsp_parser_t(): parser_t("$_nmsp") { }
};
const parser_t &ppc::comp::tree::ast::nmsp_parser = nmsp_parser_t();

View File

@ -189,7 +189,7 @@ const lexlet_t LEXLET_OPERATOR = (lexlet_t) {
},
.process = [] (char curr) {
bool failed = true;
if (first_op == curr && op_i == 1 && is_any(curr, "+-&|?<>")) failed = false;
if (first_op == curr && op_i == 1 && is_any(curr, ":+-&|?<>")) failed = false;
if (curr == '=') {
if (op_i == 1 && is_any(first_op, "<>=!+-/*%")) failed = false;
if (op_i == 2 && is_any(first_op, "<>?")) failed = false;

View File

@ -1,61 +0,0 @@
#include "compiler/treeifier/ast.hh"
#include "compiler/treeifier/ast/helper.hh"
namespace ppc::comp::tree::ast {
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 {
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;
}
};
const parser_t &glob_parser = glob_parser_t();
}

View File

@ -3,6 +3,16 @@
#include "lang/common.hh"
namespace ppc::lang {
std::string loc_namespace_name_t::to_string() const {
std::stringstream res;
for (size_t i = 0; i < size(); i++) {
if (i != 0) res << "::";
res << (*this)[i];
}
return res.str();
}
std::string namespace_name_t::to_string() const {
std::stringstream res;
@ -14,6 +24,25 @@ namespace ppc::lang {
return res.str();
}
bool loc_namespace_name_t::operator==(const loc_namespace_name_t &other) const {
if (other.size() != size()) return false;
for (size_t i = 0; i < size(); i++) {
if (other[i] != (*this)[i]) return false;
}
return true;
}
bool loc_namespace_name_t::operator!=(const loc_namespace_name_t &other) const {
if (other.size() != size()) return true;
for (size_t i = 0; i < size(); i++) {
if (other[i] == (*this)[i]) return false;
}
return true;
}
bool namespace_name_t::operator==(const namespace_name_t &other) const {
if (other.size() != size()) return false;
@ -32,5 +61,16 @@ namespace ppc::lang {
return true;
}
namespace_name_t loc_namespace_name_t::strip_location() {
namespace_name_t res;
for (const auto &el : *this) {
res.push_back(el);
}
return res;
}
}

View File

@ -101,7 +101,7 @@ int main(int argc, const char* argv[]) {
throw (std::string)"Incorrect usage. Syntax: [src-dir] [project-name] [output|deps].";
}
std::string proj_path = (std::string)argv[0] + "/" + argv[1] + "/proj.txt";
std::string proj_path = (std::string)argv[0] + "/" + argv[1] + ".proj";
proj_name = argv[1];
std::ifstream f { proj_path, std::ios_base::in };

View File

@ -24,6 +24,7 @@
#include "utils/strings.hh"
#include "compiler/treeifier/lexer.hh"
#include "compiler/treeifier/tokenizer.hh"
#include "compiler/treeifier/ast.hh"
#include "./opions.hh"
using std::cout;
@ -152,9 +153,10 @@ int main(int argc, const char *argv[]) {
for (const auto &file : files) {
std::ifstream f { file, std::ios_base::in };
try {
auto res = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f));
for (auto tok : res) {
auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f));
data::map_t ast;
if (!ast::ast_ctx_t::parse(msg_stack, tokens, ast)) throw msg_stack.peek();
for (auto tok : tokens) {
if (tok.is_identifier()) std::cout << "Identifier: \t" << tok.identifier();
if (tok.is_operator()) std::cout << "Operator: \t" << operator_stringify(tok._operator());
if (tok.is_float_lit()) std::cout << "Float: \t" << tok.float_lit();

View File

@ -1,53 +1,54 @@
#include "utils/data.hh"
bool ppc::data::value_t::is_null() const {
namespace ppc::data {
bool value_t::is_null() const {
return type == type_t::Null;
}
bool ppc::data::value_t::is_map() const {
bool value_t::is_map() const {
return type == type_t::Map;
}
bool ppc::data::value_t::is_array() const {
bool value_t::is_array() const {
return type == type_t::Arr;
}
bool ppc::data::value_t::is_number() const {
bool value_t::is_number() const {
return type == type_t::Num;
}
bool ppc::data::value_t::is_string() const {
bool value_t::is_string() const {
return type == type_t::Str;
}
bool ppc::data::value_t::is_bool() const {
bool value_t::is_bool() const {
return type == type_t::Bool;
}
bool ppc::data::value_t::array(ppc::data::array_t &out) const {
bool value_t::array(array_t &out) const {
if (is_array()) {
out = *val.arr;
return true;
}
return false;
}
bool ppc::data::value_t::map(ppc::data::map_t &out) const {
bool value_t::map(map_t &out) const {
if (is_map()) {
out = *val.map;
return true;
}
return false;
}
bool ppc::data::value_t::number(ppc::data::number_t &out) const {
bool value_t::number(number_t &out) const {
if (is_number()) {
out = val.num;
return true;
}
return false;
}
bool ppc::data::value_t::string(ppc::data::string_t &out) const {
bool value_t::string(string_t &out) const {
if (is_string()) {
out = *val.str;
return true;
}
return false;
}
bool ppc::data::value_t::boolean(ppc::data::bool_t &out) const {
bool value_t::boolean(bool_t &out) const {
if (is_bool()) {
out = val.bl;
return true;
@ -55,51 +56,51 @@ bool ppc::data::value_t::boolean(ppc::data::bool_t &out) const {
return false;
}
const ppc::data::array_t &ppc::data::value_t::array() const {
array_t &value_t::array() const {
if (is_array()) return *val.arr;
else throw (std::string)"The value isn't an array.";
}
const ppc::data::map_t &ppc::data::value_t::map() const {
map_t &value_t::map() const {
if (is_map()) return *val.map;
else throw (std::string)"The value isn't a map.";
}
ppc::data::number_t ppc::data::value_t::number() const {
number_t value_t::number() const {
if (is_number()) return val.num;
else throw (std::string)"The value isn't a number.";
}
const ppc::data::string_t &ppc::data::value_t::string() const {
string_t &value_t::string() const {
if (is_string()) return *val.str;
else throw (std::string)"The value isn't a string.";
}
ppc::data::bool_t ppc::data::value_t::boolean() const {
bool_t value_t::boolean() const {
if (is_bool()) return val.bl;
else throw (std::string)"The value isn't a bool.";
}
ppc::data::value_t::value_t() {
value_t::value_t() {
this->type = type_t::Null;
}
ppc::data::value_t::value_t(const ppc::data::array_t &val) {
value_t::value_t(const array_t &val) {
this->type = type_t::Arr;
this->val.arr = new array_t(val);
}
ppc::data::value_t::value_t(const ppc::data::map_t &val) {
value_t::value_t(const map_t &val) {
this->type = type_t::Map;
this->val.map = new map_t(val);
}
ppc::data::value_t::value_t(const ppc::data::string_t &val) {
value_t::value_t(const string_t &val) {
this->type = type_t::Str;
this->val.str = new string_t(val);
}
ppc::data::value_t::value_t(ppc::data::bool_t val) {
value_t::value_t(bool_t val) {
this->type = type_t::Bool;
this->val.bl = val;
}
ppc::data::value_t::value_t(ppc::data::number_t val) {
value_t::value_t(number_t val) {
this->type = type_t::Num;
this->val.num = val;
}
ppc::data::value_t::value_t(const ppc::data::value_t &other) {
value_t::value_t(const value_t &other) {
type = other.type;
switch (other.type) {
case type_t::Map:
@ -114,10 +115,16 @@ ppc::data::value_t::value_t(const ppc::data::value_t &other) {
default:
val = other.val;
break;
}
}
value_t value_t::mk_arr() {
return value_t(array_t());
}
value_t value_t::mk_map() {
return value_t(map_t());
}
}
}
ppc::data::value_t::~value_t() {
value_t::~value_t() {
switch (type) {
case type_t::Map:
delete val.map;
@ -133,3 +140,26 @@ ppc::data::value_t::~value_t() {
}
}
value_t::value_t(std::initializer_list<std::pair<std::string, value_t>> map):
value_t(map_t(map)) { }
value_t &value_t::operator=(const value_t &other) {
type = other.type;
switch (other.type) {
case type_t::Map:
val.map = new map_t(*other.val.map);
break;
case type_t::Arr:
val.arr = new array_t(*other.val.arr);
break;
case type_t::Str:
val.str = new string_t(*other.val.str);
break;
default:
val = other.val;
break;
}
return *this;
}
}

View File

@ -4,16 +4,17 @@
using namespace ppc;
std::string messages::message_t::to_string() const {
namespace ppc::messages {
std::string message_t::to_string() const {
std::string loc_readable = location.to_string();
std::string level_readable;
switch (level) {
case messages::message_t::DEBUG: level_readable = "debug"; break;
case messages::message_t::SUGGESTION: level_readable = "suggestion"; break;
case messages::message_t::INFO: level_readable = "info"; break;
case messages::message_t::WARNING: level_readable = "warning"; break;
case messages::message_t::ERROR: level_readable = "error"; 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;
}
@ -24,17 +25,17 @@ std::string messages::message_t::to_string() const {
return res.str();
}
bool messages::message_t::is_severe() const {
return level > messages::message_t::WARNING;
bool message_t::is_severe() const {
return level > message_t::WARNING;
}
bool messages::msg_stack_t::is_failed() const {
bool msg_stack_t::is_failed() const {
for (const auto &msg : messages) {
if (msg.is_severe()) return true;
}
return false;
}
void messages::msg_stack_t::print(std::ostream &output, messages::message_t::level_t threshold, bool color_output) const {
void msg_stack_t::print(std::ostream &output, message_t::level_t threshold, bool color_output) const {
if (!messages.size()) return;
for (const auto &msg : messages) {
@ -43,19 +44,19 @@ void messages::msg_stack_t::print(std::ostream &output, messages::message_t::lev
std::string loc_readable = msg.location.to_string();
switch (msg.level) {
case messages::message_t::DEBUG:
case message_t::DEBUG:
output << (color_output ? "\e[38;5;8mdebug: " : "debug: ");
break;
case messages::message_t::SUGGESTION:
case message_t::SUGGESTION:
output << (color_output ? "\e[38;5;45msuggestion: " : "suggestion: ");
break;
case messages::message_t::INFO:
case message_t::INFO:
output << (color_output ? "\e[38;5;33minfo: ": "info: ");
break;
case messages::message_t::WARNING:
case message_t::WARNING:
output << (color_output ? "\e[38;5;214mwarning: " : "warning: ");
break;
case messages::message_t::ERROR:
case message_t::ERROR:
output << (color_output ? "\e[38;5;196merror: " : "error: ");
break;
default:
@ -69,3 +70,4 @@ void messages::msg_stack_t::print(std::ostream &output, messages::message_t::lev
output << std::endl;
}
}
}