Merge pull request #3 from TopchetoEU/TopchetoEU/Struct-resolving
Topcheto eu/struct resolving
This commit is contained in:
commit
7d0ed9f02c
@ -26,10 +26,9 @@ namespace ppc::comp::tree::ast {
|
|||||||
std::set<std::string> unnamed_parsers;
|
std::set<std::string> unnamed_parsers;
|
||||||
std::map<std::string, parser_t> parsers;
|
std::map<std::string, parser_t> parsers;
|
||||||
public:
|
public:
|
||||||
group_t &insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after);
|
|
||||||
group_t &add_last(const std::string &name, parser_t parser);
|
|
||||||
group_t &replace(const std::string &name, parser_t parser);
|
group_t &replace(const std::string &name, parser_t parser);
|
||||||
group_t &add_named(const std::string &name, parser_t parser, const lang::namespace_name_t &identifier);
|
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;
|
bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const;
|
||||||
};
|
};
|
||||||
@ -77,7 +76,7 @@ namespace ppc::comp::tree::ast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp;
|
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;
|
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_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;
|
parser_func_t parse_exp_var, parse_exp_str_lit, parse_exp_int_lit, parse_exp_float_lit;
|
||||||
}
|
}
|
@ -1,5 +1,42 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ppc::lang {
|
||||||
|
struct namespace_name_t : public std::vector<std::string> {
|
||||||
|
using base = std::vector<std::string>;
|
||||||
|
|
||||||
|
int compare(const namespace_name_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; }
|
||||||
|
|
||||||
|
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()) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct std::hash<ppc::lang::namespace_name_t> {
|
||||||
|
std::size_t operator()(const ppc::lang::namespace_name_t& k) const {
|
||||||
|
size_t res = 0;
|
||||||
|
|
||||||
|
for (auto &el : k) {
|
||||||
|
res ^= std::hash<std::string>()(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#include "utils/message.hh"
|
#include "utils/message.hh"
|
||||||
#include "utils/location.hh"
|
#include "utils/location.hh"
|
||||||
|
|
||||||
@ -29,25 +66,6 @@ namespace ppc::lang {
|
|||||||
slocated_t() { }
|
slocated_t() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct namespace_name_t : public std::vector<std::string> {
|
|
||||||
using base = std::vector<std::string>;
|
|
||||||
|
|
||||||
int compare(const namespace_name_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; }
|
|
||||||
|
|
||||||
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>> {
|
struct loc_namespace_name_t : public std::vector<located_t<std::string>> {
|
||||||
using base = std::vector<located_t<std::string>>;
|
using base = std::vector<located_t<std::string>>;
|
||||||
|
|
||||||
|
162
include/lang/module.hh
Normal file
162
include/lang/module.hh
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#include <set>
|
||||||
|
#include <unordered_map>
|
||||||
|
#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<std::string, type_t> fields;
|
||||||
|
};
|
||||||
|
struct function_t {
|
||||||
|
std::unordered_map<std::string, type_t> 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<namespace_name_t, field_t>;
|
||||||
|
using structs_t = std::unordered_map<namespace_name_t, struct_t>;
|
||||||
|
using funcs_t = std::unordered_map<namespace_name_t, function_t>;
|
||||||
|
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 <class T>
|
||||||
|
struct resolve_res_t {
|
||||||
|
namespace_name_t name;
|
||||||
|
T value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool resolve_name(
|
||||||
|
const std::vector<namespace_name_t> &names, const std::set<namespace_name_t> &imports,
|
||||||
|
const namespace_name_t &name, namespace_name_t &res
|
||||||
|
);
|
||||||
|
|
||||||
|
template <class MapT>
|
||||||
|
bool resolve_name_map(
|
||||||
|
const MapT &defs, const std::set<namespace_name_t> &imports,
|
||||||
|
const namespace_name_t &name, namespace_name_t &res
|
||||||
|
) {
|
||||||
|
std::vector<namespace_name_t> names;
|
||||||
|
for (auto &it : defs) {
|
||||||
|
const namespace_name_t &val = it.first;
|
||||||
|
names.push_back(val);
|
||||||
|
}
|
||||||
|
return resolve_name(names, imports, name, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class MapT>
|
||||||
|
bool resolve(
|
||||||
|
const MapT &defs, const std::set<namespace_name_t> &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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "lang/common.hh"
|
|
||||||
#include "lang/types.hh"
|
|
||||||
#include "lang/version.hh"
|
|
||||||
|
|
||||||
namespace ppc::lang {
|
|
||||||
// A structure, containing all the definitions of a namespace
|
|
||||||
struct namespace_t {
|
|
||||||
// The name of the namespace
|
|
||||||
namespace_name_t name;
|
|
||||||
// The version of the namespace
|
|
||||||
version_t version;
|
|
||||||
// A list of all the defined types inside the namespace
|
|
||||||
std::vector<ppc::lang::type_def_t> types;
|
|
||||||
// A list of all the defined fields inside the namespace
|
|
||||||
std::vector<field_t> fields;
|
|
||||||
|
|
||||||
bool contains_def(const std::string &name, location_t &ploc) const;
|
|
||||||
inline bool contains_def(const std::string &name) const {
|
|
||||||
location_t ploc;
|
|
||||||
return contains_def(name, ploc);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
static bool contains_def(T namespaces, const namespace_name_t &def_nmsp, const std::string &name, location_t &ploc) {
|
|
||||||
for (const namespace_t &nmsp : namespaces) {
|
|
||||||
if (nmsp.name == def_nmsp && nmsp.contains_def(name)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
static inline bool contains_def(T namespaces, const namespace_name_t &def_nmsp, const std::string &name) {
|
|
||||||
location_t ploc;
|
|
||||||
return contains_def(namespaces, def_nmsp, name, ploc);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
enum operator_t {
|
|
||||||
OPERATOR_NONE,
|
|
||||||
OPERATOR_LESS_THAN,
|
|
||||||
OPERATOR_GREATER_THAN,
|
|
||||||
OPERATOR_LESS_THAN_EQUALS,
|
|
||||||
OPERATOR_GREATER_THAN_EQUALS,
|
|
||||||
OPERATOR_EQUALS,
|
|
||||||
OPERATOR_NOT_EQUALS,
|
|
||||||
OPERATOR_BOOLEAN_AND,
|
|
||||||
OPERATOR_BOOLEAN_OR,
|
|
||||||
|
|
||||||
OPERATOR_SHIFT_LEFT,
|
|
||||||
OPERATOR_SHIFT_RIGHT,
|
|
||||||
OPERATOR_BINARY_XOR,
|
|
||||||
OPERATOR_BINARY_AND,
|
|
||||||
OPERATOR_BINARY_OR,
|
|
||||||
OPERATOR_BOOLEAN_NOT,
|
|
||||||
OPERATOR_BITWISE_NEGATIVE,
|
|
||||||
|
|
||||||
OPERATOR_INCREASE,
|
|
||||||
OPERATOR_DECREASE,
|
|
||||||
|
|
||||||
OPERATOR_POST_INCREASE,
|
|
||||||
OPERATOR_POST_DECREASE,
|
|
||||||
|
|
||||||
OPERATOR_ADD,
|
|
||||||
OPERATOR_SUBTRACT,
|
|
||||||
OPERATOR_DIVIDE,
|
|
||||||
OPERATOR_MULTIPLY,
|
|
||||||
OPERATOR_MODULO,
|
|
||||||
|
|
||||||
OPERATOR_POSITIVE,
|
|
||||||
OPERATOR_NEGATIVE,
|
|
||||||
|
|
||||||
OPERATOR_CONDITIONAL,
|
|
||||||
OPERATOR_NULL_COALESCING,
|
|
||||||
|
|
||||||
OPERATOR_IMPLICIT,
|
|
||||||
OPERATOR_EXPLICIT,
|
|
||||||
|
|
||||||
OPERATOR_NEW,
|
|
||||||
OPERATOR_VAL,
|
|
||||||
|
|
||||||
OPERATOR_ASSIGN,
|
|
||||||
|
|
||||||
OPERATOR_PTR_MEMBER,
|
|
||||||
OPERATOR_MEMBER,
|
|
||||||
|
|
||||||
OPERATOR_REFERENCING,
|
|
||||||
OPERATOR_DEREFERENCING,
|
|
||||||
|
|
||||||
OPERATOR_CALL,
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "utils/location.hh"
|
|
||||||
#include "lang/common.hh"
|
|
||||||
#include "lang/version.hh"
|
|
||||||
|
|
||||||
namespace ppc::lang {
|
|
||||||
enum def_type_kind_t {
|
|
||||||
TYPE_NONE,
|
|
||||||
TYPE_STRUCT,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct type_def_t;
|
|
||||||
|
|
||||||
// A structure, representing a ++C type notation
|
|
||||||
struct type_t {
|
|
||||||
// The type definition of which this type is
|
|
||||||
// If NULL, then this type is unknown
|
|
||||||
// Feel free to scream at the user if this is NULL
|
|
||||||
type_def_t *def;
|
|
||||||
};
|
|
||||||
// A structure, representing a field in a ++C struct
|
|
||||||
struct field_t {
|
|
||||||
// The type of which this field is
|
|
||||||
type_t type;
|
|
||||||
// The name of the field
|
|
||||||
const char *name;
|
|
||||||
// Whether or not the field is exported
|
|
||||||
bool is_exported;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A structure, representing a ++C type (structs, classes, delegates and interfaces)
|
|
||||||
struct type_def_t {
|
|
||||||
// Whether or not this definition is exported
|
|
||||||
bool is_exported;
|
|
||||||
// The namespace of the type
|
|
||||||
namespace_name_t _namespace;
|
|
||||||
// The name of the type
|
|
||||||
const char *name;
|
|
||||||
// The version of the type (inherited from the module version)
|
|
||||||
version_t version;
|
|
||||||
// The location of the definition
|
|
||||||
location_t location;
|
|
||||||
|
|
||||||
// The alignment padding from the start of the structures, in bytes
|
|
||||||
// Used either for efficiency sake or to store private fields (or both)
|
|
||||||
std::size_t align_size;
|
|
||||||
// A list of all the type's fields
|
|
||||||
std::vector<field_t> fields;
|
|
||||||
};
|
|
||||||
}
|
|
@ -99,6 +99,10 @@ namespace ppc::data {
|
|||||||
return values.find(key) != values.end();
|
return values.find(key) != values.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
values.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t size() const { return values.size(); }
|
std::size_t size() const { return values.size(); }
|
||||||
|
|
||||||
auto begin() const { return values.begin(); }
|
auto begin() const { return values.begin(); }
|
||||||
|
@ -12,20 +12,23 @@ group_t &ast_ctx_t::group(const std::string &name) {
|
|||||||
|
|
||||||
ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens): messages(messages), tokens(tokens) {
|
ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens): messages(messages), tokens(tokens) {
|
||||||
group("$_exp_val")
|
group("$_exp_val")
|
||||||
.add_last("$_var", parse_exp_var)
|
.add("$_var", parse_exp_var)
|
||||||
.add_last("$_int", parse_exp_int_lit)
|
.add("$_int", parse_exp_int_lit)
|
||||||
.add_last("$_string", parse_exp_str_lit);
|
.add("$_string", parse_exp_str_lit);
|
||||||
// .add_last("$_float", parse_exp_float_lit)
|
// .add_last("$_float", parse_exp_float_lit)
|
||||||
group("$_stat")
|
group("$_stat")
|
||||||
.add_named("$_while", parse_while, { "while" })
|
.add("$_while", { "while" }, parse_while)
|
||||||
.add_named("$_if", parse_if, { "if" })
|
.add("$_if", { "if" }, parse_if)
|
||||||
.add_named("$_return", parse_return, { "return" })
|
.add("$_return", { "return" }, parse_return)
|
||||||
.add_named("$_break", parse_break, { "break" })
|
.add("$_break", { "break" }, parse_break)
|
||||||
.add_named("$_continue", parse_continue, { "continue" })
|
.add("$_continue", { "continue" }, parse_continue)
|
||||||
.add_last("$_comp", parse_stat_comp)
|
.add("$_comp", parse_stat_comp)
|
||||||
.add_last("$_exp", parse_stat_exp);
|
.add("$_exp", parse_stat_exp);
|
||||||
group("$_def")
|
group("$_def")
|
||||||
.add_last("$_func", parse_func)
|
.add("$_func", parse_func)
|
||||||
.add_named("$_export", parse_export, { "export" })
|
.add("$_struct", { "struct" }, parse_struct)
|
||||||
.add_last("$_field", parse_field);
|
.add("$_field", parse_field);
|
||||||
|
group("$_struct_def")
|
||||||
|
.add("$_func", parse_func)
|
||||||
|
.add("$_field", parse_field);
|
||||||
}
|
}
|
@ -3,10 +3,14 @@
|
|||||||
bool ast::parse_export(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
bool ast::parse_export(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||||
tree_helper_t h(ctx, res_i);
|
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()) {
|
if (out["exported"].is_true()) {
|
||||||
ctx.messages.push(message_t(message_t::WARNING, "Export is alredy specified for this definition.", h.prev_loc()));
|
ctx.messages.push(message_t(message_t::WARNING, "Export is alredy specified for this definition.", h.prev_loc()));
|
||||||
}
|
}
|
||||||
out["exported"] = true;
|
out["exported"] = true;
|
||||||
|
|
||||||
return ctx.group("$_def")(ctx, res_i, out);
|
return h.submit(false);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ bool ast::parse_field(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
|||||||
|
|
||||||
if (h.ended()) return false;
|
if (h.ended()) return false;
|
||||||
|
|
||||||
|
h.parse(parse_export, out);
|
||||||
|
|
||||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||||
|
|
||||||
bool type = false, defval = false;
|
bool type = false, defval = false;
|
||||||
|
@ -5,6 +5,8 @@ static bool parse_arg(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
|||||||
|
|
||||||
if (h.ended()) return false;
|
if (h.ended()) return false;
|
||||||
|
|
||||||
|
h.parse(parse_export, out);
|
||||||
|
|
||||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||||
|
|
||||||
bool type = false, defval = false;
|
bool type = false, defval = false;
|
||||||
@ -34,6 +36,8 @@ bool ast::parse_func(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
|||||||
|
|
||||||
if (h.ended()) return false;
|
if (h.ended()) return false;
|
||||||
|
|
||||||
|
h.parse(parse_export, out);
|
||||||
|
|
||||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||||
if (h.ended()) return false;
|
if (h.ended()) return false;
|
||||||
if (!h.curr().is_operator(operator_t::PAREN_OPEN)) return false;
|
if (!h.curr().is_operator(operator_t::PAREN_OPEN)) return false;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "lang/module.hh"
|
||||||
#include "compiler/treeifier/ast.hh"
|
#include "compiler/treeifier/ast.hh"
|
||||||
#include "compiler/treeifier/tokenizer.hh"
|
#include "compiler/treeifier/tokenizer.hh"
|
||||||
#include "compiler/treeifier/ast/helper.hh"
|
#include "compiler/treeifier/ast/helper.hh"
|
||||||
@ -18,45 +19,8 @@ static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &nam
|
|||||||
name = conv::map_to_nmsp(res);
|
name = conv::map_to_nmsp(res);
|
||||||
return h.submit(false);
|
return h.submit(false);
|
||||||
}
|
}
|
||||||
template <class T>
|
|
||||||
static bool resolve_nmsp(ast_ctx_t &ctx, const lang::namespace_name_t &name, T begin, T end, lang::namespace_name_t &actual_name) {
|
|
||||||
for (auto it = begin; it != end; it++) {
|
|
||||||
const namespace_name_t &curr = it->first;
|
|
||||||
if (curr == name) {
|
|
||||||
actual_name = name;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const auto &import : ctx.imports) {
|
|
||||||
auto new_name = name;
|
|
||||||
new_name.insert(new_name.begin(), import.begin(), import.end());
|
|
||||||
for (auto it = begin; it != end; it++) {
|
|
||||||
const namespace_name_t &curr = it->first;
|
|
||||||
if (curr == new_name) {
|
|
||||||
actual_name = name;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
group_t &group_t::insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after) {
|
|
||||||
if (parsers.find(name) != parsers.end()) {
|
|
||||||
throw "The parser '" + name + "' is already in the group.";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = unnamed_parsers.find(relative_to);
|
|
||||||
if (it == unnamed_parsers.end()) {
|
|
||||||
throw "The parser '" + relative_to + "' isn't in the group or isn't unnamed.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (after) it++;
|
|
||||||
|
|
||||||
unnamed_parsers.insert(it, name);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
group_t &group_t::replace(const std::string &name, parser_t parser) {
|
group_t &group_t::replace(const std::string &name, parser_t parser) {
|
||||||
auto it = parsers.find(name);
|
auto it = parsers.find(name);
|
||||||
|
|
||||||
@ -68,7 +32,7 @@ group_t &group_t::replace(const std::string &name, parser_t parser) {
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
group_t &group_t::add_last(const std::string &name, parser_t parser) {
|
group_t &group_t::add(const std::string &name, parser_t parser) {
|
||||||
if (parsers.find(name) != parsers.end()) {
|
if (parsers.find(name) != parsers.end()) {
|
||||||
throw "The parser '" + name + "' is already in the group.";
|
throw "The parser '" + name + "' is already in the group.";
|
||||||
}
|
}
|
||||||
@ -78,7 +42,7 @@ group_t &group_t::add_last(const std::string &name, parser_t parser) {
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
group_t &group_t::add_named(const std::string &name, parser_t parser, const lang::namespace_name_t &identifier) {
|
group_t &group_t::add(const std::string &name, const lang::namespace_name_t &identifier, parser_t parser) {
|
||||||
if (parsers.find(name) != parsers.end()) {
|
if (parsers.find(name) != parsers.end()) {
|
||||||
throw "The parser '" + name + "' is already in the group.";
|
throw "The parser '" + name + "' is already in the group.";
|
||||||
}
|
}
|
||||||
@ -94,11 +58,20 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
|
|||||||
|
|
||||||
if (h.ended()) return false;
|
if (h.ended()) return false;
|
||||||
|
|
||||||
|
std::set<namespace_name_t> names;
|
||||||
|
|
||||||
|
for (auto &import : ctx.imports) names.insert(import.strip_location());
|
||||||
|
|
||||||
loc_namespace_name_t name;
|
loc_namespace_name_t name;
|
||||||
if (read_nmsp(ctx, h.i, name)) {
|
if (read_nmsp(ctx, h.i, name)) {
|
||||||
namespace_name_t actual;
|
namespace_name_t actual;
|
||||||
if (resolve_nmsp(ctx, name.strip_location(), named_parsers.begin(), named_parsers.end(), actual)) {
|
|
||||||
|
if (resolve_name_map(
|
||||||
|
named_parsers, names,
|
||||||
|
name.strip_location(), actual
|
||||||
|
)) {
|
||||||
auto parser = parsers.find(this->named_parsers.find(actual)->second);
|
auto parser = parsers.find(this->named_parsers.find(actual)->second);
|
||||||
|
out.clear();
|
||||||
out["$_name"] = parser->first;
|
out["$_name"] = parser->first;
|
||||||
if (h.parse(parser->second, out)) return h.submit(false);
|
if (h.parse(parser->second, out)) return h.submit(false);
|
||||||
else throw message_t::error("Unexpected construct specifier.", h.res_loc());
|
else throw message_t::error("Unexpected construct specifier.", h.res_loc());
|
||||||
@ -107,6 +80,7 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
|
|||||||
|
|
||||||
for (auto name : unnamed_parsers) {
|
for (auto name : unnamed_parsers) {
|
||||||
out["$_name"] = name;
|
out["$_name"] = name;
|
||||||
|
out.clear();
|
||||||
if (parsers.at(name)(ctx, i, out)) return true;
|
if (parsers.at(name)(ctx, i, out)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/compiler/treeifier/ast/parsers/struct.cc
Normal file
24
src/compiler/treeifier/ast/parsers/struct.cc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#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);
|
||||||
|
}
|
88
src/lang/module.cc
Normal file
88
src/lang/module.cc
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#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<namespace_name_t> &names, const std::set<namespace_name_t> &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;
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
struct project_t {
|
struct project_t {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
Loading…
Reference in New Issue
Block a user