chore: major recoding, imports and namespaces
This commit is contained in:
parent
0a3e65a24b
commit
c8043fab9a
@ -1,6 +1,6 @@
|
||||
#ifndef PPC_COMPILER_H
|
||||
#define PPC_COMPILER_H 1
|
||||
|
||||
#include "compiler/treeifier.hh"
|
||||
#include "treeifier.hh"
|
||||
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
#ifndef PPC_TREEIFIER_H
|
||||
#define PPC_TREEIFIER_H 1
|
||||
|
||||
#include "utils/message.hh"
|
||||
|
||||
namespace ppc::compiler {
|
||||
// bool treeify(ppc::messages::msg_stack_t &msg_stack, const std::string &filename, const std::string &source, namespace_t *pout);
|
||||
// bool treeify_file(const std::string &filename, ppc::messages::msg_stack_t &pmsg_stack, namespace_t *pout);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,105 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "compiler/treeifier/tokenizer.hh"
|
||||
#include "lang/common.hh"
|
||||
#include "utils/data.hh"
|
||||
|
||||
using namespace std::string_literals;
|
||||
using namespace ppc;
|
||||
using namespace ppc::lang;
|
||||
using namespace ppc::messages;
|
||||
|
||||
namespace ppc::comp::tree::ast {
|
||||
struct ast_ctx_t;
|
||||
using parser_func_t = bool(ast_ctx_t &ctx, size_t &res_i, data::map_t &out);
|
||||
using parser_t = parser_func_t *;
|
||||
|
||||
class group_t {
|
||||
private:
|
||||
std::map<lang::namespace_name_t, std::string> named_parsers;
|
||||
std::set<std::string> unnamed_parsers;
|
||||
std::map<std::string, parser_t> parsers;
|
||||
public:
|
||||
group_t &replace(const std::string &name, parser_t parser);
|
||||
group_t &add(const std::string &name, parser_t parser);
|
||||
group_t &add(const std::string &name, const lang::namespace_name_t &identifier, parser_t parser);
|
||||
|
||||
bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const;
|
||||
};
|
||||
|
||||
struct ast_ctx_t {
|
||||
private:
|
||||
std::unordered_map<std::string, group_t> groups;
|
||||
public:
|
||||
msg_stack_t &messages;
|
||||
std::vector<token_t> &tokens;
|
||||
std::set<loc_namespace_name_t> imports;
|
||||
loc_namespace_name_t nmsp;
|
||||
|
||||
ast_ctx_t &operator=(const ast_ctx_t &other) = delete;
|
||||
|
||||
template <class T>
|
||||
bool parse(const T &parser, size_t &i, data::map_t &out) {
|
||||
return parser(*this, i, out);
|
||||
}
|
||||
|
||||
group_t &group(const std::string &name);
|
||||
|
||||
template <class T>
|
||||
static data::map_t parse(const T &glob, msg_stack_t &messages, std::vector<token_t> &tokens) {
|
||||
ast_ctx_t ctx(messages, tokens);
|
||||
data::map_t res;
|
||||
size_t i = 0;
|
||||
|
||||
if (!ctx.parse(glob, i, res)) throw message_t::error("Failed to compile.");
|
||||
return res;
|
||||
}
|
||||
|
||||
ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens);
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
data::string_t loc_to_map(const location_t &loc);
|
||||
location_t map_to_loc(const data::string_t &map);
|
||||
|
||||
data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp);
|
||||
loc_namespace_name_t map_to_nmsp(const data::map_t &map);
|
||||
} // namespace conv
|
||||
|
||||
class construct_t {
|
||||
public:
|
||||
virtual const std::string &name() const = 0;
|
||||
};
|
||||
|
||||
class parser_t {
|
||||
public:
|
||||
virtual bool parse(ast_ctx_t &ctx, size_t &res_i, construct_t *&out) const = 0;
|
||||
virtual bool simplify(ast_ctx_t &ctx, size_t &res_i, const construct_t *global, const construct_t *container, const construct_t *current) const = 0;
|
||||
};
|
||||
|
||||
namespace constr {
|
||||
class glob_con_t: public construct_t {
|
||||
const std::string &name() const { return "$_glob"s; }
|
||||
bool parse(ast_ctx_t &ctx, size_t &res_i, construct_t *&out) const;
|
||||
};
|
||||
}
|
||||
|
||||
namespace parsers {
|
||||
|
||||
}
|
||||
|
||||
parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp;
|
||||
parser_func_t parse_func, parse_field, parse_export, parse_struct;
|
||||
parser_func_t parse_if, parse_while, parse_return, parse_break, parse_continue, parse_stat_comp;
|
||||
parser_func_t parse_exp_var, parse_exp_str_lit, parse_exp_int_lit, parse_exp_float_lit;
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
#include <string>
|
||||
|
||||
namespace ppc::lang {
|
||||
struct namespace_name_t : public std::vector<std::string> {
|
||||
struct namespace_name_t: public std::vector<std::string> {
|
||||
using base = std::vector<std::string>;
|
||||
|
||||
int compare(const namespace_name_t &other) const;
|
||||
@ -42,7 +42,7 @@ struct std::hash<ppc::lang::namespace_name_t> {
|
||||
|
||||
namespace ppc::lang {
|
||||
template <class T>
|
||||
struct located_t : T {
|
||||
struct located_t: T {
|
||||
location_t location;
|
||||
|
||||
located_t(location_t loc, const T &val): T(val), location(loc) { }
|
||||
@ -66,7 +66,7 @@ namespace ppc::lang {
|
||||
slocated_t() { }
|
||||
};
|
||||
|
||||
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>>;
|
||||
|
||||
int compare(const loc_namespace_name_t &other) const;
|
||||
|
94
include/treeifier/constr.hh
Normal file
94
include/treeifier/constr.hh
Normal file
@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include "lang/common.hh"
|
||||
#include "treeifier/tokenizer.hh"
|
||||
#include "utils/data.hh"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace std::string_literals;
|
||||
using namespace ppc;
|
||||
using namespace ppc::lang;
|
||||
using namespace ppc::messages;
|
||||
|
||||
namespace ppc::tree::constr {
|
||||
struct ast_ctx_t;
|
||||
|
||||
struct glob_t {
|
||||
loc_namespace_name_t nmsp;
|
||||
std::vector<loc_namespace_name_t> imports;
|
||||
};
|
||||
|
||||
template <class T, class GlobT = glob_t>
|
||||
class parser_t {
|
||||
public:
|
||||
virtual bool operator()(ast_ctx_t &ctx, size_t &res_i, T &out) const = 0;
|
||||
virtual bool simplify(ast_ctx_t &ctx, GlobT &glob, T &val) const = 0;
|
||||
#ifdef PROFILE_debug
|
||||
virtual void print(const T &val) {
|
||||
std::cout << "(unknown)";
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct ast_ctx_t {
|
||||
public:
|
||||
msg_stack_t &messages;
|
||||
std::vector<token_t> &tokens;
|
||||
loc_namespace_name_t nmsp;
|
||||
|
||||
ast_ctx_t &operator=(const ast_ctx_t &other) = delete;
|
||||
|
||||
template <class T>
|
||||
bool parse(const parser_t<T> &parser, size_t &i, T &out) {
|
||||
return parser(*this, i, out);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T parse(const parser_t<T> &glob, msg_stack_t &messages, std::vector<token_t> &tokens) {
|
||||
ast_ctx_t ctx(messages, tokens);
|
||||
T res;
|
||||
size_t i = 0;
|
||||
|
||||
if (!ctx.parse(glob, i, res)) throw message_t::error("Failed to compile.");
|
||||
return res;
|
||||
}
|
||||
|
||||
ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class inspoint_t {
|
||||
private:
|
||||
std::map<lang::namespace_name_t, std::string> named_parsers;
|
||||
std::set<std::string> unnamed_parsers;
|
||||
std::map<std::string, T *> parsers;
|
||||
public:
|
||||
inspoint_t &replace(const std::string &name, const T &parser) {
|
||||
auto it = parsers.find(name);
|
||||
|
||||
if (parsers.find(name) == parsers.end()) {
|
||||
throw "The parser '" + name + "' isn't in the group.";
|
||||
}
|
||||
|
||||
it->second = parser;
|
||||
|
||||
return *this;
|
||||
}
|
||||
inspoint_t &add(const std::string &name, const T &parser);
|
||||
inspoint_t &add(const std::string &name, const lang::namespace_name_t &identifier, const T &parser);
|
||||
|
||||
bool operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const;
|
||||
};
|
||||
|
||||
// parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp;
|
||||
// parser_func_t parse_func, parse_field, parse_export, parse_struct;
|
||||
// parser_func_t parse_if, parse_while, parse_return, parse_break, parse_continue, parse_stat_comp;
|
||||
// parser_func_t parse_exp_var, parse_exp_str_lit, parse_exp_int_lit, parse_exp_float_lit;
|
||||
}
|
9
include/treeifier/constr/glob.hh
Normal file
9
include/treeifier/constr/glob.hh
Normal file
@ -0,0 +1,9 @@
|
||||
#include "treeifier/constr.hh"
|
||||
|
||||
namespace ppc::tree::constr {
|
||||
class glob_parser_t: public parser_t<glob_t> {
|
||||
public:
|
||||
bool operator()(ast_ctx_t &ctx, size_t &res_i, glob_t &out) const override;
|
||||
bool simplify(ast_ctx_t &ctx, glob_t &glob, glob_t &val) const override { return false; }
|
||||
};
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
#include "compiler/treeifier/ast.hh"
|
||||
#include "treeifier/constr.hh"
|
||||
|
||||
using namespace ppc;
|
||||
using namespace ppc::lang;
|
||||
using namespace ppc::data;
|
||||
using namespace ppc::comp::tree;
|
||||
using namespace ppc::comp::tree::ast;
|
||||
using namespace ppc::tree;
|
||||
using namespace ppc::tree::constr;
|
||||
|
||||
namespace ppc::comp::tree::ast {
|
||||
struct tree_helper_t {
|
||||
namespace ppc::tree::constr {
|
||||
struct parse_helper_t {
|
||||
private:
|
||||
ast_ctx_t &ctx;
|
||||
size_t &res_i;
|
||||
@ -105,37 +105,12 @@ namespace ppc::comp::tree::ast {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool push_parse(const T &parser, data::array_t &out) {
|
||||
data::map_t res;
|
||||
if (parse(parser, res)) {
|
||||
out.push_back(res);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool parse(const T &parser, data::map_t &out) {
|
||||
bool parse(const parser_t<T> &parser, T &out) {
|
||||
return ctx.parse(parser, i, out);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void force_push_parse(const T &parser, std::string message, data::array_t &out) {
|
||||
throw_ended(message);
|
||||
bool success;
|
||||
|
||||
try {
|
||||
success = push_parse(parser, out);
|
||||
}
|
||||
catch (const message_t &msg) {
|
||||
ctx.messages.push(msg);
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success) err(message);
|
||||
}
|
||||
template <class T>
|
||||
void force_parse(const T &parser, std::string message, data::map_t &out) {
|
||||
void force_parse(const parser_t<T> &parser, std::string message, T &out) {
|
||||
throw_ended(message);
|
||||
bool success;
|
||||
|
||||
@ -150,7 +125,7 @@ namespace ppc::comp::tree::ast {
|
||||
if (!success) err(message);
|
||||
}
|
||||
|
||||
tree_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) {
|
||||
parse_helper_t(ast_ctx_t &ctx, size_t &i): ctx(ctx), res_i(i) {
|
||||
this->i = i;
|
||||
}
|
||||
};
|
8
include/treeifier/constr/identifier.hh
Normal file
8
include/treeifier/constr/identifier.hh
Normal file
@ -0,0 +1,8 @@
|
||||
#include "treeifier/constr.hh"
|
||||
|
||||
namespace ppc::tree::constr {
|
||||
struct identifier_parser_t: public parser_t<located_t<std::string>> {
|
||||
bool operator()(ast_ctx_t &ctx, size_t &res_i, located_t<std::string> &out) const override;
|
||||
bool simplify(ast_ctx_t &ctx, glob_t &glob, located_t<std::string> &val) const override { return false; }
|
||||
};
|
||||
}
|
9
include/treeifier/constr/nmsp.hh
Normal file
9
include/treeifier/constr/nmsp.hh
Normal file
@ -0,0 +1,9 @@
|
||||
#include "treeifier/constr/identifier.hh"
|
||||
#include "treeifier/constr.hh"
|
||||
|
||||
namespace ppc::tree::constr {
|
||||
struct nmsp_parser_t: public parser_t<loc_namespace_name_t> {
|
||||
bool operator()(ast_ctx_t &ctx, size_t &res_i, loc_namespace_name_t &out) const override;
|
||||
bool simplify(ast_ctx_t &ctx, glob_t &glob, loc_namespace_name_t &val) const override { return false; }
|
||||
};
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
#include "utils/location.hh"
|
||||
#include "utils/message.hh"
|
||||
|
||||
namespace ppc::comp::tree::lex {
|
||||
namespace ppc::tree::lex {
|
||||
struct token_t {
|
||||
enum kind_t {
|
||||
NONE,
|
@ -2,9 +2,9 @@
|
||||
|
||||
#include "utils/location.hh"
|
||||
#include "utils/message.hh"
|
||||
#include "compiler/treeifier/lexer.hh"
|
||||
#include "treeifier/lexer.hh"
|
||||
|
||||
namespace ppc::comp::tree {
|
||||
namespace ppc::tree {
|
||||
enum operator_t {
|
||||
NONE,
|
||||
|
@ -116,5 +116,5 @@ namespace ppc::data {
|
||||
}
|
||||
};
|
||||
|
||||
class array_t : public std::vector<value_t> { };
|
||||
class array_t: public std::vector<value_t> { };
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#include "compiler/treeifier/ast.hh"
|
||||
|
||||
using namespace ppc;
|
||||
using namespace ppc::data;
|
||||
using namespace ppc::lang;
|
||||
using namespace ppc::comp::tree::ast;
|
||||
|
||||
group_t &ast_ctx_t::group(const std::string &name) {
|
||||
if (groups.find(name) == groups.end()) return groups[name] = {};
|
||||
else return groups[name];
|
||||
}
|
||||
|
||||
ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens):
|
||||
messages(messages), tokens(tokens) {
|
||||
group("$_exp_val")
|
||||
.add("$_var", parse_exp_var)
|
||||
.add("$_int", parse_exp_int_lit)
|
||||
.add("$_string", parse_exp_str_lit);
|
||||
// .add_last("$_float", parse_exp_float_lit)
|
||||
group("$_stat")
|
||||
.add("$_while", { "while" }, parse_while)
|
||||
.add("$_if", { "if" }, parse_if)
|
||||
.add("$_return", { "return" }, parse_return)
|
||||
.add("$_break", { "break" }, parse_break)
|
||||
.add("$_continue", { "continue" }, parse_continue)
|
||||
.add("$_comp", parse_stat_comp)
|
||||
.add("$_exp", parse_stat_exp);
|
||||
group("$_def")
|
||||
.add("$_func", parse_func)
|
||||
.add("$_struct", { "struct" }, parse_struct)
|
||||
.add("$_field", parse_field);
|
||||
group("$_struct_def")
|
||||
.add("$_func", parse_func)
|
||||
.add("$_field", parse_field);
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
#include "compiler/treeifier/ast.hh"
|
||||
#include <sstream>
|
||||
|
||||
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" },
|
||||
};
|
||||
}
|
||||
located_t<std::string> map_to_identifier(const data::map_t &map) {
|
||||
return { conv::map_to_loc(map["location"].string()), map["content"].string() };
|
||||
}
|
||||
|
||||
data::string_t loc_to_map(const location_t &loc) {
|
||||
std::stringstream res;
|
||||
res << loc.filename << ':' << loc.line + 1 << ':' << loc.start + 1 << ':' << loc.code_start + 1 << ':' << loc.length + 1;
|
||||
return res.str();
|
||||
}
|
||||
location_t map_to_loc(const data::string_t &map) {
|
||||
std::stringstream res;
|
||||
res.str(map);
|
||||
|
||||
std::string filename;
|
||||
std::string line;
|
||||
std::string start;
|
||||
std::string code_start;
|
||||
std::string length;
|
||||
|
||||
std::getline(res, filename, ':');
|
||||
std::getline(res, line, ':');
|
||||
std::getline(res, start, ':');
|
||||
std::getline(res, code_start, ':');
|
||||
std::getline(res, length, ':');
|
||||
|
||||
return { filename, std::stoull(line) - 1, std::stoull(start) - 1, std::stoull(code_start) - 1, std::stoull(length) - 1 };
|
||||
}
|
||||
|
||||
data::map_t nmsp_to_map(const loc_namespace_name_t &nmsp) {
|
||||
data::map_t res;
|
||||
|
||||
auto arr = res["content"].array({});
|
||||
|
||||
for (const auto &segment : nmsp) {
|
||||
arr.push_back({
|
||||
{ "location", loc_to_map(segment.location) },
|
||||
{ "content", segment },
|
||||
{ "$_name", "$_nmsp" },
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
loc_namespace_name_t map_to_nmsp(const data::map_t &map) {
|
||||
loc_namespace_name_t res;
|
||||
|
||||
for (const auto &segment : map["content"].array()) {
|
||||
try {
|
||||
auto val = map_to_identifier(segment.map());
|
||||
res.push_back(val);
|
||||
}
|
||||
catch (const message_t &) {
|
||||
throw "'content' of a namespace map must contain only identifiers.";
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
@ -1,364 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
enum precedence_t {
|
||||
NONE,
|
||||
POSTFIX,
|
||||
PREFIX,
|
||||
MULT,
|
||||
ADD,
|
||||
SHIFT,
|
||||
COMP,
|
||||
EQU,
|
||||
BIN_AND,
|
||||
BIN_XOR,
|
||||
BIN_OR,
|
||||
BOOL_AND,
|
||||
BOOL_OR,
|
||||
TERNARY,
|
||||
ASSIGN,
|
||||
PAREN,
|
||||
CALL_START,
|
||||
};
|
||||
|
||||
struct op_data_t {
|
||||
precedence_t precedence;
|
||||
size_t op_n;
|
||||
std::string name;
|
||||
bool assoc;
|
||||
};
|
||||
|
||||
op_data_t sizeof_data { precedence_t::PREFIX, 1, "sizeof", true };
|
||||
|
||||
std::map<operator_t, op_data_t> pre_ops {
|
||||
{ operator_t::INCREASE, { precedence_t::PREFIX, 1, "inc_pre" } },
|
||||
{ operator_t::DECREASE, { precedence_t::PREFIX, 1, "dec_pre" } },
|
||||
{ operator_t::ADD, { precedence_t::PREFIX, 1, "positive" } },
|
||||
{ operator_t::SUBTRACT, { precedence_t::PREFIX, 1, "negative" } },
|
||||
{ operator_t::BITWISE_NEGATIVE, { precedence_t::PREFIX, 1, "flip" } },
|
||||
{ operator_t::MULTIPLY, { precedence_t::PREFIX, 1, "dereference" } },
|
||||
{ operator_t::AND, { precedence_t::PREFIX, 1, "reference" } },
|
||||
};
|
||||
std::map<operator_t, op_data_t> bin_ops {
|
||||
{ operator_t::INCREASE, { precedence_t::POSTFIX, 1, "inc_post" } },
|
||||
{ operator_t::DECREASE, { precedence_t::POSTFIX, 1, "dec_post" } },
|
||||
{ (operator_t)-1, sizeof_data },
|
||||
|
||||
{ operator_t::ADD, { precedence_t::ADD, 2, "add" } },
|
||||
{ operator_t::SUBTRACT, { precedence_t::ADD, 2, "subtract" } },
|
||||
|
||||
{ operator_t::MULTIPLY, { precedence_t::MULT, 2, "multiply" } },
|
||||
{ operator_t::DIVIDE, { precedence_t::MULT, 2, "divide" } },
|
||||
{ operator_t::MODULO, { precedence_t::MULT, 2, "modulo" } },
|
||||
|
||||
{ operator_t::SHIFT_LEFT, { precedence_t::SHIFT, 2, "shl" } },
|
||||
{ operator_t::SHIFT_RIGHT, { precedence_t::SHIFT, 2, "shr" } },
|
||||
|
||||
{ operator_t::LESS_THAN, { precedence_t::COMP, 2, "less" } },
|
||||
{ operator_t::LESS_THAN_EQUALS, { precedence_t::COMP, 2, "less_eq" } },
|
||||
{ operator_t::GREATER_THAN, { precedence_t::COMP, 2, "great" } },
|
||||
{ operator_t::GREATER_THAN_EQUALS, { precedence_t::COMP, 2, "great_eq" } },
|
||||
|
||||
{ operator_t::EQUALS, { precedence_t::EQU, 2, "eq" } },
|
||||
{ operator_t::NOT_EQUALS, { precedence_t::EQU, 2, "neq" } },
|
||||
|
||||
{ operator_t::AND, { precedence_t::BIN_AND, 2, "great_eq" } },
|
||||
{ operator_t::OR, { precedence_t::BIN_OR, 2, "great_eq" } },
|
||||
{ operator_t::XOR, { precedence_t::BIN_XOR, 2, "great_eq" } },
|
||||
|
||||
{ operator_t::DOUBLE_AND, { precedence_t::BOOL_AND, 2, "great_eq" } },
|
||||
{ operator_t::DOUBLE_OR, { precedence_t::BOOL_OR, 2, "great_eq" } },
|
||||
|
||||
{ operator_t::ASSIGN, { precedence_t::ASSIGN, 2, "assign", true } },
|
||||
{ operator_t::ASSIGN_ADD, { precedence_t::ASSIGN, 2, "assign_add", true } },
|
||||
{ operator_t::ASSIGN_SUBTRACT, { precedence_t::ASSIGN, 2, "assign_subtract", true } },
|
||||
{ operator_t::ASSIGN_MULTIPLY, { precedence_t::ASSIGN, 2, "assign_multiply", true } },
|
||||
{ operator_t::ASSIGN_DIVIDE, { precedence_t::ASSIGN, 2, "assign_divide", true } },
|
||||
{ operator_t::ASSIGN_MODULO, { precedence_t::ASSIGN, 2, "assign_modulo", true } },
|
||||
{ operator_t::ASSIGN_SHIFT_LEFT, { precedence_t::ASSIGN, 2, "assign_shl", true } },
|
||||
{ operator_t::ASSIGN_SHIFT_RIGHT, { precedence_t::ASSIGN, 2, "assign_shr", true } },
|
||||
{ operator_t::ASSIGN_XOR, { precedence_t::ASSIGN, 2, "assign_xor", true } },
|
||||
{ operator_t::ASSIGN_AND, { precedence_t::ASSIGN, 2, "assign_and", true } },
|
||||
{ operator_t::ASSIGN_OR, { precedence_t::ASSIGN, 2, "assign_or", true } },
|
||||
{ operator_t::ASSIGN_DOUBLE_AND, { precedence_t::ASSIGN, 2, "assign_dand", true } },
|
||||
{ operator_t::ASSIGN_DOUBLE_OR, { precedence_t::ASSIGN, 2, "assign_dor", true } },
|
||||
{ operator_t::ASSIGN_NULL_COALESCING, { precedence_t::ASSIGN, 2, "assign_null_coal", true } },
|
||||
};
|
||||
|
||||
map_t op_to_map(located_t<op_data_t> op) {
|
||||
return {
|
||||
{ "$_name", "$_operator" },
|
||||
{ "ops", array_t() },
|
||||
{ "location", conv::loc_to_map(op.location) },
|
||||
{ "op", op.name },
|
||||
};
|
||||
}
|
||||
|
||||
bool pop(std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||
if (op_stack.empty()) return false;
|
||||
|
||||
auto map = op_to_map(op_stack.back());
|
||||
auto op_n = op_stack.back().op_n;
|
||||
auto loc = op_stack.back().location;
|
||||
op_stack.pop_back();
|
||||
|
||||
if (res.size() < op_n) return false;
|
||||
|
||||
auto &ops = map["ops"].array();
|
||||
|
||||
|
||||
for (size_t i = 0; i < op_n; i++) {
|
||||
ops.push_back(res.back());
|
||||
loc = loc.intersect(conv::map_to_loc(res.back().map()["location"].string()));
|
||||
res.pop_back();
|
||||
}
|
||||
|
||||
map["location"] = conv::loc_to_map(loc);
|
||||
|
||||
std::reverse(ops.begin(), ops.end());
|
||||
res.push_back(map);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool pop_paren(std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||
bool has_paren = false;
|
||||
for (const auto &op : op_stack) {
|
||||
if (op.precedence == precedence_t::PAREN) {
|
||||
has_paren = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_paren) return false;
|
||||
|
||||
while (true) {
|
||||
if (op_stack.back().precedence == precedence_t::PAREN) break;
|
||||
if (!pop(op_stack, res)) return false;
|
||||
}
|
||||
|
||||
op_stack.pop_back();
|
||||
return true;
|
||||
}
|
||||
bool pop_call(size_t n, location_t loc, std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||
map_t call = {
|
||||
{ "$_name", "$_call" },
|
||||
};
|
||||
|
||||
array_t &args = call["args"].array({});
|
||||
|
||||
while (true) {
|
||||
if (op_stack.back().precedence == precedence_t::CALL_START) break;
|
||||
if (!pop(op_stack, res)) return false;
|
||||
}
|
||||
loc = loc.intersect(op_stack.back().location);
|
||||
op_stack.pop_back();
|
||||
call["location"] = conv::loc_to_map(loc);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
args.push_back(res.back());
|
||||
res.pop_back();
|
||||
}
|
||||
|
||||
std::reverse(args.begin(), args.end());
|
||||
|
||||
call["func"] = res.back();
|
||||
res.pop_back();
|
||||
res.push_back(call);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool pop_until(const op_data_t &data, tree_helper_t &h, std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||
while (!op_stack.empty()) {
|
||||
auto &back_data = op_stack.back();
|
||||
if (data.assoc ? back_data.precedence >= data.precedence : back_data.precedence > data.precedence) break;
|
||||
|
||||
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast::parse_exp_var(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
return ctx.parse(parse_nmsp, res_i, out);
|
||||
}
|
||||
bool ast::parse_exp_int_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.curr().is_int_literal()) {
|
||||
auto &arr = out["content"].array({});
|
||||
for (auto b : h.curr().literal()) {
|
||||
arr.push_back((float)b);
|
||||
}
|
||||
out["location"] = conv::loc_to_map(h.loc());
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool ast::parse_exp_str_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.curr().is_str_literal()) {
|
||||
auto &arr = out["content"].array({});
|
||||
for (auto b : h.curr().literal()) {
|
||||
arr.push_back((float)b);
|
||||
}
|
||||
out["location"] = conv::loc_to_map(h.loc());
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ast::parse_exp(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
bool last_val = false;
|
||||
map_t val;
|
||||
std::vector<located_t<op_data_t>> op_stack;
|
||||
std::vector<size_t> call_args_n;
|
||||
auto res = array_t();
|
||||
|
||||
|
||||
while (true) {
|
||||
if (h.ended()) break;
|
||||
|
||||
if (!last_val && h.curr().is_identifier("sizeof")) {
|
||||
op_stack.push_back({ h.loc(), sizeof_data });
|
||||
h.advance("Expected a value on the right side of the operator.");
|
||||
continue;
|
||||
}
|
||||
if (!last_val && h.push_parse(ctx.group("$_exp_val"), res)) {
|
||||
last_val = true;
|
||||
continue;
|
||||
}
|
||||
if (h.curr().is_operator()) {
|
||||
auto op = h.curr()._operator();
|
||||
if (last_val) {
|
||||
if (op == operator_t::PAREN_OPEN) {
|
||||
h.advance("Expected an argument or closing parens.");
|
||||
op_stack.push_back({ h.loc(), { precedence_t::CALL_START } });
|
||||
if (h.curr().is_operator(operator_t::PAREN_CLOSE)) {
|
||||
pop_call(0, h.loc(), op_stack, res);
|
||||
}
|
||||
else {
|
||||
call_args_n.push_back(1);
|
||||
}
|
||||
last_val = false;
|
||||
}
|
||||
else if (op == operator_t::PAREN_CLOSE) {
|
||||
bool is_call = false, is_paren = false;
|
||||
|
||||
for (auto i = op_stack.rbegin(); i != op_stack.rend(); i++) {
|
||||
if (i->precedence == precedence_t::PAREN) {
|
||||
is_paren = true;
|
||||
break;
|
||||
}
|
||||
else if (i->precedence == precedence_t::CALL_START) {
|
||||
is_call = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_call) {
|
||||
pop_call(call_args_n.back(), h.loc(), op_stack, res);
|
||||
call_args_n.pop_back();
|
||||
}
|
||||
else if (is_paren) pop_paren(op_stack, res);
|
||||
else break;
|
||||
|
||||
if (!h.try_advance()) break;
|
||||
}
|
||||
else if (op == operator_t::COMMA) {
|
||||
if (call_args_n.size() == 0) break;
|
||||
h.advance("Expected an argument.");
|
||||
|
||||
pop_until({ .precedence = precedence_t::CALL_START, .assoc = true }, h, op_stack, res);
|
||||
call_args_n.back()++;
|
||||
last_val = false;
|
||||
}
|
||||
else if (op == operator_t::COLON) {
|
||||
h.advance("Expected a type.");
|
||||
pop_until({ .precedence = precedence_t::PREFIX, .assoc = true }, h, op_stack, res);
|
||||
map_t cast = {
|
||||
{ "$_name", "$_cast" },
|
||||
{ "exp", res.back() },
|
||||
};
|
||||
|
||||
res.pop_back();
|
||||
h.force_parse(parse_type, "Expected a type.", cast["type"].map({}));
|
||||
cast["location"] = conv::loc_to_map(location_t::intersect(
|
||||
conv::map_to_loc(cast["exp"].map()["location"].string()),
|
||||
conv::map_to_loc(cast["type"].map()["location"].string())
|
||||
));
|
||||
res.push_back(cast);
|
||||
}
|
||||
else if (op == operator_t::DOT || op == operator_t::PTR_MEMBER) {
|
||||
h.advance("Expected an identifier.");
|
||||
pop_until({ .precedence = precedence_t::POSTFIX, .assoc = true }, h, op_stack, res);
|
||||
|
||||
map_t member_access = {
|
||||
{ "exp", res.back() },
|
||||
{ "is_ptr", op == operator_t::PTR_MEMBER },
|
||||
};
|
||||
h.force_parse(parse_identifier, "Expected an identifier.", member_access["name"].map({}));
|
||||
member_access["location"] = conv::loc_to_map(
|
||||
conv::map_to_loc(member_access["name"].map()["location"].string())
|
||||
.intersect(conv::map_to_loc(res.back().map()["location"].string()))
|
||||
);
|
||||
res.pop_back();
|
||||
res.push_back(member_access);
|
||||
}
|
||||
else if (bin_ops.find(op) != bin_ops.end()) {
|
||||
auto data = bin_ops[op];
|
||||
pop_until(data, h, op_stack, res);
|
||||
op_stack.push_back({ h.loc(), data });
|
||||
|
||||
if (data.op_n == 1) {
|
||||
last_val = true;
|
||||
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
||||
if (h.try_advance()) break;
|
||||
}
|
||||
else {
|
||||
last_val = false;
|
||||
h.advance("Expected a value on the right side of the operator.");
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else {
|
||||
if (op == operator_t::PAREN_OPEN) {
|
||||
op_stack.push_back({ h.loc(), { precedence_t::PAREN } });
|
||||
h.advance("Expected a value.");
|
||||
last_val = false;
|
||||
}
|
||||
else if (pre_ops.find(op) != pre_ops.end()) {
|
||||
op_stack.push_back({ h.loc(), pre_ops[op] });
|
||||
h.advance("Expected a value on the right side of the operator.");
|
||||
}
|
||||
else break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if (res.size() == 0) return false;
|
||||
|
||||
while (!op_stack.empty()) {
|
||||
if (op_stack.back().precedence == precedence_t::PAREN) throw message_t::error("Unclosed paren.", op_stack.back().location);
|
||||
if (op_stack.back().precedence == precedence_t::CALL_START) throw message_t::error("Unclosed call.", op_stack.back().location);
|
||||
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
||||
}
|
||||
|
||||
out = res.front().map();
|
||||
|
||||
return h.submit(false);
|
||||
}
|
||||
bool ast::parse_stat_exp(ast_ctx_t &ctx, size_t &i, map_t &res) {
|
||||
tree_helper_t h(ctx, i);
|
||||
if (!h.parse(parse_exp, res)) return false;
|
||||
if (!h.ended() && h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true);
|
||||
|
||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
||||
return h.submit(false);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_export(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
if (!h.curr().is_identifier("export")) return false;
|
||||
h.advance("Unexpected end after export.");
|
||||
|
||||
if (out["exported"].is_true()) {
|
||||
ctx.messages.push(message_t(message_t::WARNING, "Export is alredy specified for this definition.", h.prev_loc()));
|
||||
}
|
||||
out["exported"] = true;
|
||||
|
||||
return h.submit(false);
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_field(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
h.parse(parse_export, out);
|
||||
|
||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||
|
||||
bool type = false, defval = false;
|
||||
|
||||
h.throw_ended("Expected a colon or an equals sign.");
|
||||
|
||||
if (h.curr().is_operator(operator_t::COLON)) {
|
||||
h.advance();
|
||||
h.force_parse(parse_type, "Expected a type.", out["type"].map({}));
|
||||
type = true;
|
||||
}
|
||||
if (h.curr().is_operator(operator_t::ASSIGN)) {
|
||||
h.advance();
|
||||
h.force_parse(parse_exp, "Expected an expression.", out["value"].map({}));
|
||||
type = true;
|
||||
}
|
||||
|
||||
if (!h.ended() && h.curr().is_operator(operator_t::SEMICOLON)) {
|
||||
if (type || defval) return h.submit();
|
||||
else return h.err("A type or a default value must be specified ");
|
||||
}
|
||||
else if (type || defval) {
|
||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
||||
return h.submit(false);
|
||||
}
|
||||
else return false;
|
||||
|
||||
return h.submit(true);
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
static bool parse_arg(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
h.parse(parse_export, out);
|
||||
|
||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||
|
||||
bool type = false, defval = false;
|
||||
|
||||
h.throw_ended("Expected a colon or an equals sign.");
|
||||
|
||||
if (h.curr().is_operator(operator_t::COLON)) {
|
||||
h.advance();
|
||||
h.force_parse(parse_type, "Expected a type.", out["type"].map({}));
|
||||
type = true;
|
||||
}
|
||||
if (h.curr().is_operator(operator_t::ASSIGN)) {
|
||||
h.advance();
|
||||
h.force_parse(parse_exp, "Expected an expression.", out["value"].map({}));
|
||||
type = true;
|
||||
}
|
||||
|
||||
if (!type && !defval) {
|
||||
ctx.messages.push(message_t::error("Expected a type or a default value.", h.loc(1)));
|
||||
}
|
||||
|
||||
return h.submit(false);
|
||||
}
|
||||
|
||||
bool ast::parse_func(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
h.parse(parse_export, out);
|
||||
|
||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||
if (h.ended()) return false;
|
||||
if (!h.curr().is_operator(operator_t::PAREN_OPEN)) return false;
|
||||
h.advance("Expected a closing paren or a parameter.");
|
||||
|
||||
auto ¶ms = out["params"].array({});
|
||||
auto &content = out["content"].array({});
|
||||
|
||||
while (true) {
|
||||
if (h.curr().is_operator(operator_t::PAREN_CLOSE)) {
|
||||
h.advance("Expected a function body.");
|
||||
break;
|
||||
}
|
||||
h.force_push_parse(parse_arg, "Expected a parameter.", params);
|
||||
if (h.curr().is_operator(operator_t::COMMA)) {
|
||||
h.advance("Expected a parameter.");
|
||||
}
|
||||
}
|
||||
|
||||
if (h.curr().is_operator(operator_t::COLON)) {
|
||||
h.advance("Expected a type.");
|
||||
h.force_parse(parse_type, "Expected a type", out["type"].map({}));
|
||||
}
|
||||
|
||||
if (h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true);
|
||||
else if (h.curr().is_operator(operator_t::LAMBDA)) {
|
||||
h.advance("Expected an expression.");
|
||||
map_t exp;
|
||||
h.force_parse(parse_exp, "Expected an expression.", exp);
|
||||
content.push_back({
|
||||
{ "$_name", "$_return" },
|
||||
{ "content", exp },
|
||||
});
|
||||
return h.submit(false);
|
||||
}
|
||||
else if (h.curr().is_operator(operator_t::BRACE_OPEN)) {
|
||||
h.advance("Expected a statement.");
|
||||
while (true) {
|
||||
if (h.curr().is_operator(operator_t::BRACE_CLOSE)) {
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
h.force_push_parse(ctx.group("$_stat"), "Expected an expression.", content);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.messages.push(message_t::error("Expected a semicolon, brace open or a lambda operator.", h.loc(1)));
|
||||
return h.submit(false);
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
#include "compiler/treeifier/ast.hh"
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
using namespace ppc::comp::tree::ast;
|
||||
|
||||
static bool nmsp_def(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
if (h.ended()) return false;
|
||||
|
||||
if (!h.curr().is_identifier("namespace")) return false;
|
||||
h.advance("Expected a namespace");
|
||||
h.force_parse(parse_nmsp, "Expected a namespace.", res);
|
||||
if (!h.curr().is_operator(operator_t::SEMICOLON)) {
|
||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
||||
return h.submit(false);
|
||||
}
|
||||
return h.submit(true);
|
||||
}
|
||||
static bool import(ast_ctx_t &ctx, size_t &res_i, data::map_t &res) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
if (h.ended()) return false;
|
||||
|
||||
if (!h.curr().is_identifier("import")) return false;
|
||||
h.advance("Expected a namespace");
|
||||
h.force_parse(parse_nmsp, "Expected a namespace.", res);
|
||||
if (!h.curr().is_operator(operator_t::SEMICOLON)) {
|
||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
||||
return h.submit(false);
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
bool ast::parse_glob(ast_ctx_t &ctx, size_t &res_i, data::map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return true;
|
||||
if (h.parse(nmsp_def, out["namespace"].map({}))) {
|
||||
ctx.nmsp = conv::map_to_nmsp(out["namespace"].map());
|
||||
}
|
||||
else {
|
||||
out["namespace"] = data::null;
|
||||
}
|
||||
|
||||
auto &imports = out["imports"].array({});
|
||||
auto &contents = out["content"].array({});
|
||||
|
||||
while (true) {
|
||||
map_t map;
|
||||
if (!h.parse(import, map)) break;
|
||||
imports.push_back(map);
|
||||
auto nmsp = conv::map_to_nmsp(map);
|
||||
|
||||
if (!ctx.imports.emplace(nmsp).second) h.err("The namespace '" + nmsp.to_string() + "' is already imported.");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (h.ended()) break;
|
||||
if (!h.push_parse(ctx.group("$_def"), contents)) {
|
||||
ctx.messages.push(message_t::error("Invalid token.", h.loc()));
|
||||
h.i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!h.ended()) h.err("Invalid token.");
|
||||
|
||||
return h.submit();
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
#include "lang/module.hh"
|
||||
#include "compiler/treeifier/ast.hh"
|
||||
#include "compiler/treeifier/tokenizer.hh"
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using namespace ppc::comp::tree;
|
||||
using namespace ppc::comp::tree::ast;
|
||||
using namespace std::string_literals;
|
||||
using namespace std;
|
||||
|
||||
static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &name) {
|
||||
tree_helper_t h(ctx, i);
|
||||
map_t res;
|
||||
if (!h.parse(parse_nmsp, res)) return false;
|
||||
name = conv::map_to_nmsp(res);
|
||||
return h.submit(false);
|
||||
}
|
||||
|
||||
|
||||
group_t &group_t::replace(const std::string &name, parser_t parser) {
|
||||
auto it = parsers.find(name);
|
||||
|
||||
if (parsers.find(name) == parsers.end()) {
|
||||
throw "The parser '" + name + "' isn't in the group.";
|
||||
}
|
||||
|
||||
it->second = parser;
|
||||
|
||||
return *this;
|
||||
}
|
||||
group_t &group_t::add(const std::string &name, parser_t parser) {
|
||||
if (parsers.find(name) != parsers.end()) {
|
||||
throw "The parser '" + name + "' is already in the group.";
|
||||
}
|
||||
|
||||
parsers.emplace(name, parser);
|
||||
unnamed_parsers.emplace(name);
|
||||
|
||||
return *this;
|
||||
}
|
||||
group_t &group_t::add(const std::string &name, const lang::namespace_name_t &identifier, parser_t parser) {
|
||||
if (parsers.find(name) != parsers.end()) {
|
||||
throw "The parser '" + name + "' is already in the group.";
|
||||
}
|
||||
|
||||
parsers.emplace(name, parser);
|
||||
named_parsers.emplace(identifier, name);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
|
||||
tree_helper_t h(ctx, i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
std::set<namespace_name_t> names;
|
||||
|
||||
for (auto &import : ctx.imports) names.insert(import.strip_location());
|
||||
|
||||
loc_namespace_name_t name;
|
||||
if (read_nmsp(ctx, h.i, name)) {
|
||||
namespace_name_t actual;
|
||||
|
||||
if (resolve_name_map(
|
||||
named_parsers, names,
|
||||
name.strip_location(), actual
|
||||
)) {
|
||||
auto parser = parsers.find(this->named_parsers.find(actual)->second);
|
||||
out.clear();
|
||||
out["$_name"] = parser->first;
|
||||
if (h.parse(parser->second, out)) return h.submit(false);
|
||||
else throw message_t::error("Unexpected construct specifier.", h.res_loc());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto name : unnamed_parsers) {
|
||||
out["$_name"] = name;
|
||||
out.clear();
|
||||
if (parsers.at(name)(ctx, i, out)) return true;
|
||||
}
|
||||
|
||||
stringstream m;
|
||||
|
||||
return false;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_identifier(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
if (h.curr().is_identifier()) {
|
||||
auto loc = h.loc();
|
||||
out["location"] = conv::loc_to_map(loc);
|
||||
out["content"] = h.curr().identifier();
|
||||
return h.submit();
|
||||
}
|
||||
else return false;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_nmsp(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
auto &arr = (out["content"] = array_t()).array();
|
||||
|
||||
if (!h.push_parse(parse_identifier, arr)) return false;
|
||||
|
||||
while (true) {
|
||||
if (h.ended()) break;
|
||||
if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break;
|
||||
h.advance("Expected an identifier.");
|
||||
h.force_push_parse(parse_identifier, "Expected an identifier.", arr);
|
||||
}
|
||||
|
||||
out["location"] = conv::loc_to_map(h.res_loc());
|
||||
return h.submit(false);
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_if(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
h.throw_ended("Expected open parens after if keyword.");
|
||||
if (!h.curr("Expected open parens after if keyword.").is_operator(operator_t::PAREN_OPEN)) {
|
||||
throw message_t::error("Expected open parens after if keyword.", h.loc(1));
|
||||
}
|
||||
|
||||
h.advance("Expected an expression.");
|
||||
h.force_parse(parse_exp, "Expected an expression.", out["condition"].map({}));
|
||||
|
||||
if (!h.curr("Expected closed parens.").is_operator(operator_t::PAREN_CLOSE)) {
|
||||
throw message_t::error("Expected closed parens.", h.loc(1));
|
||||
}
|
||||
|
||||
h.advance("Expected a statement.");
|
||||
h.force_parse(ctx.group("$_stat"), "Expected a statement.", out["if"].map({}));
|
||||
|
||||
if (h.ended() || !h.curr().is_identifier("else")) return h.submit(false);
|
||||
|
||||
h.advance("Expected a statement.");
|
||||
h.force_parse(ctx.group("$_stat"), "Expected a statement.", out["else"].map({}));
|
||||
|
||||
return h.submit(false);
|
||||
}
|
||||
|
||||
bool ast::parse_while(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
h.throw_ended("Expected open parens after while keyword.");
|
||||
if (!h.curr("Expected open parens after while keyword.").is_operator(operator_t::PAREN_OPEN)) {
|
||||
throw message_t::error("Expected open parens after while keyword.", h.loc(1));
|
||||
}
|
||||
|
||||
h.advance("Expected an expression.");
|
||||
h.force_parse(parse_exp, "Expected an expression.", out["condition"].map({}));
|
||||
|
||||
if (!h.curr("Expected closed parens.").is_operator(operator_t::PAREN_CLOSE)) {
|
||||
throw message_t::error("Expected closed parens.", h.loc(1));
|
||||
}
|
||||
|
||||
h.advance("Expected a statement.");
|
||||
h.force_parse(ctx.group("$_stat"), "Expected a statement.", out["while"].map({}));
|
||||
|
||||
return h.submit(false);
|
||||
}
|
||||
|
||||
bool ast::parse_return(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
h.throw_ended("Expected an expression.");
|
||||
h.force_parse(parse_exp, "Expected an expression.", out["condition"].map({}));
|
||||
|
||||
if (!h.curr("Expected a semicolon.").is_operator(operator_t::SEMICOLON)) {
|
||||
throw message_t::error("Expected a semicolon.", h.loc(1));
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
bool ast::parse_break(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (!h.curr("Expected a semicolon.").is_operator(operator_t::SEMICOLON)) {
|
||||
throw message_t::error("Expected a semicolon.", h.loc(1));
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
bool ast::parse_continue(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (!h.curr("Expected a semicolon.").is_operator(operator_t::SEMICOLON)) {
|
||||
throw message_t::error("Expected a semicolon.", h.loc(1));
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
||||
|
||||
bool ast::parse_stat_comp(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
if (!h.curr().is_operator(operator_t::BRACE_OPEN)) return false;
|
||||
h.advance("Expected a statement or a closing brace.");
|
||||
|
||||
auto &content = out["content"].array({});
|
||||
|
||||
while (!h.curr().is_operator(operator_t::BRACE_CLOSE)) {
|
||||
h.throw_ended("Expected a statement or a closing brace.");
|
||||
h.push_parse(ctx.group("$_stat"), content);
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_struct(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
if (!h.parse(parse_identifier, out["name"].map({}))) return false;
|
||||
|
||||
auto &content = out["content"].array({});
|
||||
|
||||
if (h.ended()) return false;
|
||||
if (h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true);
|
||||
if (!h.curr().is_operator(operator_t::BRACE_OPEN)) return false;
|
||||
h.advance("Expected a definition, a closing brace, or a semicolon.");
|
||||
|
||||
|
||||
while (!h.curr().is_operator(operator_t::BRACE_CLOSE)) {
|
||||
h.throw_ended("Expected a definition or a closing brace.");
|
||||
h.push_parse(ctx.group("$_struct_def"), content);
|
||||
}
|
||||
|
||||
return h.submit(true);
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#include "compiler/treeifier/ast/helper.hh"
|
||||
|
||||
bool ast::parse_type(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||
tree_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
auto &nmsp = out["namespace"].map({});
|
||||
size_t ptr_n = 0;
|
||||
|
||||
if (!h.parse(parse_nmsp, nmsp)) return false;
|
||||
|
||||
while (!h.ended() && h.curr().is_operator(operator_t::MULTIPLY)) {
|
||||
ptr_n++;
|
||||
if (!h.try_advance()) break;
|
||||
}
|
||||
|
||||
auto &nmsp_arr = nmsp["content"].array();
|
||||
|
||||
h.i--;
|
||||
out["location"] = conv::loc_to_map(h.res_loc());
|
||||
h.i++;
|
||||
out["name"] = nmsp_arr.back();
|
||||
out["ptr_n"] = (float)ptr_n;
|
||||
nmsp_arr.pop_back();
|
||||
if (nmsp_arr.empty()) out["namespace"] = null;
|
||||
else {
|
||||
auto loc_1 = conv::map_to_loc(nmsp_arr.front().map()["location"].string());
|
||||
auto loc_2 = conv::map_to_loc(nmsp_arr.back().map()["location"].string());
|
||||
auto loc = loc_1.intersect(loc_2);
|
||||
nmsp["location"] = conv::loc_to_map(loc);
|
||||
}
|
||||
|
||||
return h.submit(false);
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
main
|
||||
utils, compiler
|
||||
utils, treeifier
|
150
src/main/main.cc
150
src/main/main.cc
@ -17,9 +17,10 @@
|
||||
#endif
|
||||
|
||||
#include "./opions.hh"
|
||||
#include "compiler/treeifier/ast.hh"
|
||||
#include "compiler/treeifier/lexer.hh"
|
||||
#include "compiler/treeifier/tokenizer.hh"
|
||||
#include "treeifier/constr.hh"
|
||||
#include "treeifier/constr/glob.hh"
|
||||
#include "treeifier/lexer.hh"
|
||||
#include "treeifier/tokenizer.hh"
|
||||
#include "utils/json.hh"
|
||||
#include "utils/strings.hh"
|
||||
#include "utils/threading.hh"
|
||||
@ -31,83 +32,87 @@
|
||||
using std::cout;
|
||||
using std::size_t;
|
||||
using namespace ppc;
|
||||
using namespace ppc::comp::tree;
|
||||
using namespace ppc::comp::tree::ast;
|
||||
using namespace ppc::tree;
|
||||
using namespace ppc::tree::constr;
|
||||
|
||||
void add_flags(options::parser_t &parser) {
|
||||
parser.add_flag({ .name = "version",
|
||||
.shorthands = "v",
|
||||
.description = "Displays version and license agreement of this binary",
|
||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||
cout << "++C compiler\n"
|
||||
<< " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD
|
||||
parser.add_flag({
|
||||
.name = "version",
|
||||
.shorthands = "v",
|
||||
.description = "Displays version and license agreement of this binary",
|
||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||
cout << "++C compiler\n";
|
||||
cout << " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD;
|
||||
#if WINDOWS
|
||||
<< " (Windows)"
|
||||
cout << " (Windows)";
|
||||
#elif LINUX
|
||||
<< " (Linux)"
|
||||
cout << " (Linux)";
|
||||
#endif
|
||||
<< "\n"
|
||||
<< " License: MIT Copyright (C) TopchetoEU\n";
|
||||
exit(0);
|
||||
} });
|
||||
parser.add_flag({ .name = "help",
|
||||
.shorthands = "h",
|
||||
.description = "Displays a list of all flags and their meaning",
|
||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||
cout << "Usage: ...flags ...files\n\n"
|
||||
<< "Flags and file names can be interlaced\n"
|
||||
<< "Flags will execute in the order they're written, then compilation begins\n\n"
|
||||
<< "Flags:\n";
|
||||
cout << "\n";
|
||||
cout << " License: MIT Copyright (C) TopchetoEU\n";
|
||||
exit(0);
|
||||
}
|
||||
});
|
||||
parser.add_flag({
|
||||
.name = "help",
|
||||
.shorthands = "h",
|
||||
.description = "Displays a list of all flags and their meaning",
|
||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||
cout << "Usage: ...flags ...files\n\n";
|
||||
cout << "Flags and file names can be interlaced\n";
|
||||
cout << "Flags will execute in the order they're written, then compilation begins\n\n";
|
||||
cout << "Flags:\n";
|
||||
|
||||
for (const auto &flag : parser) {
|
||||
std::stringstream buff;
|
||||
buff << " --" << flag.name;
|
||||
for (const auto &flag : parser) {
|
||||
std::stringstream buff;
|
||||
buff << " --" << flag.name;
|
||||
|
||||
if (flag.match_type) buff << "=...";
|
||||
if (flag.shorthands.size()) {
|
||||
buff << " (";
|
||||
bool first = true;
|
||||
for (char shorthand : flag.shorthands) {
|
||||
if (!first) buff << ",";
|
||||
else first = false;
|
||||
if (flag.match_type) buff << "=...";
|
||||
if (flag.shorthands.size()) {
|
||||
buff << " (";
|
||||
bool first = true;
|
||||
for (char shorthand : flag.shorthands) {
|
||||
if (!first) buff << ",";
|
||||
else first = false;
|
||||
|
||||
buff << " -";
|
||||
buff << std::string { shorthand };
|
||||
}
|
||||
buff << ")";
|
||||
}
|
||||
buff << " -";
|
||||
buff << std::string { shorthand };
|
||||
}
|
||||
buff << ")";
|
||||
}
|
||||
|
||||
buff << " ";
|
||||
buff << " ";
|
||||
|
||||
cout << buff.str();
|
||||
size_t n = buff.str().length();
|
||||
cout << buff.str();
|
||||
size_t n = buff.str().length();
|
||||
|
||||
if (flag.description.size()) {
|
||||
const size_t padding = 24;
|
||||
const size_t msg_width = 80 - padding;
|
||||
if (flag.description.size()) {
|
||||
const size_t padding = 24;
|
||||
const size_t msg_width = 80 - padding;
|
||||
|
||||
for (size_t i = 0; i < padding - n; i++)
|
||||
cout << ' ';
|
||||
for (size_t i = 0; i < padding - n; i++)
|
||||
cout << ' ';
|
||||
|
||||
int len = flag.description.length();
|
||||
int len = flag.description.length();
|
||||
|
||||
for (size_t i = 0; i < len / msg_width; i++) {
|
||||
for (size_t j = 0; j < msg_width; j++)
|
||||
cout << flag.description[i * msg_width + j];
|
||||
cout << std::endl;
|
||||
for (size_t j = 0; j < padding; j++)
|
||||
cout << ' ';
|
||||
}
|
||||
for (size_t i = 0; i < len / msg_width; i++) {
|
||||
for (size_t j = 0; j < msg_width; j++)
|
||||
cout << flag.description[i * msg_width + j];
|
||||
cout << std::endl;
|
||||
for (size_t j = 0; j < padding; j++)
|
||||
cout << ' ';
|
||||
}
|
||||
|
||||
int remainder = len % msg_width;
|
||||
int remainder = len % msg_width;
|
||||
|
||||
for (int i = 0; i < remainder; i++)
|
||||
cout << flag.description[len - remainder + i];
|
||||
}
|
||||
for (int i = 0; i < remainder; i++)
|
||||
cout << flag.description[len - remainder + i];
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
} });
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
});
|
||||
parser.add_flag({
|
||||
.name = "silent",
|
||||
.shorthands = "qs",
|
||||
@ -118,12 +123,14 @@ void add_flags(options::parser_t &parser) {
|
||||
.description = "Sets a lower limit of messages that will print. Accepted values: 'all', 'debug', 'suggestion', 'info', 'warning', 'error', 'none'",
|
||||
.match_type = options::MATCH_PREFIX,
|
||||
});
|
||||
parser.add_flag({ .name = "print-what",
|
||||
.description = "Prints a 'what?' type of message (you'll see)",
|
||||
.match_type = options::MATCH_PREFIX,
|
||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||
global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL."));
|
||||
} });
|
||||
parser.add_flag({
|
||||
.name = "print-what",
|
||||
.description = "Prints a 'what?' type of message (you'll see)",
|
||||
.match_type = options::MATCH_PREFIX,
|
||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||
global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
@ -156,9 +163,8 @@ int main(int argc, const char *argv[]) {
|
||||
std::ifstream f { file, std::ios_base::in };
|
||||
if (!f.is_open()) throw message_t::error("The file doesn't exist.", { file });
|
||||
auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f));
|
||||
auto ast = ast_ctx_t::parse(ast::parse_glob, msg_stack, tokens);
|
||||
|
||||
std::cout << data::json::stringify(ast) << std::endl;
|
||||
auto ast = ast_ctx_t::parse(constr::glob_parser_t(), msg_stack, tokens);
|
||||
// std::cout << data::json::stringify(ast) << std::endl;
|
||||
}
|
||||
catch (const messages::message_t &msg) {
|
||||
msg_stack.push(msg);
|
||||
|
@ -1,2 +1,2 @@
|
||||
compiler
|
||||
treeifier
|
||||
utils, lang
|
36
src/treeifier/ast.cc
Normal file
36
src/treeifier/ast.cc
Normal file
@ -0,0 +1,36 @@
|
||||
#include "treeifier/constr.hh"
|
||||
#include <iostream>
|
||||
|
||||
using namespace ppc;
|
||||
using namespace ppc::data;
|
||||
using namespace ppc::lang;
|
||||
using namespace ppc::tree::constr;
|
||||
|
||||
// ppc::tree::constr::inspoint_t &ast_ctx_t::group(const std::string &name) {
|
||||
// if (groups.find(name) == groups.end()) return groups[name] = {};
|
||||
// else return groups[name];
|
||||
// }
|
||||
|
||||
ast_ctx_t::ast_ctx_t(msg_stack_t &messages, std::vector<token_t> &tokens):
|
||||
messages(messages), tokens(tokens) {
|
||||
// group("$_exp_val")
|
||||
// .add("$_var", parse_exp_var)
|
||||
// .add("$_int", parse_exp_int_lit)
|
||||
// .add("$_string", parse_exp_str_lit);
|
||||
// // .add_last("$_float", parse_exp_float_lit)
|
||||
// group("$_stat")
|
||||
// .add("$_while", { "while" }, parse_while)
|
||||
// .add("$_if", { "if" }, parse_if)
|
||||
// .add("$_return", { "return" }, parse_return)
|
||||
// .add("$_break", { "break" }, parse_break)
|
||||
// .add("$_continue", { "continue" }, parse_continue)
|
||||
// .add("$_comp", parse_stat_comp)
|
||||
// .add("$_exp", parse_stat_exp);
|
||||
// group("$_def")
|
||||
// .add("$_func", parse_func)
|
||||
// .add("$_struct", { "struct" }, parse_struct)
|
||||
// .add("$_field", parse_field);
|
||||
// group("$_struct_def")
|
||||
// .add("$_func", parse_func)
|
||||
// .add("$_field", parse_field);
|
||||
}
|
41
src/treeifier/constr/glob.cc
Normal file
41
src/treeifier/constr/glob.cc
Normal file
@ -0,0 +1,41 @@
|
||||
#include "treeifier/constr/glob.hh"
|
||||
#include "treeifier/constr/helper.hh"
|
||||
#include "treeifier/constr/nmsp.hh"
|
||||
|
||||
using namespace ppc::tree::constr;
|
||||
|
||||
bool ppc::tree::constr::glob_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, glob_t &out) const {
|
||||
parse_helper_t h(ctx, res_i);
|
||||
out = {};
|
||||
|
||||
if (h.ended()) return h.submit(false);
|
||||
|
||||
if (h.curr().is_identifier("namespace")) {
|
||||
h.advance("Expected a namespace");
|
||||
h.force_parse(nmsp_parser_t(), "Expected a namespace.", out.nmsp);
|
||||
|
||||
if (!h.curr().is_operator(operator_t::SEMICOLON)) {
|
||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
||||
}
|
||||
|
||||
if (!h.try_advance()) return h.submit(false);
|
||||
}
|
||||
|
||||
while (h.curr().is_identifier("import")) {
|
||||
loc_namespace_name_t res;
|
||||
|
||||
h.advance("Expected a namespace");
|
||||
h.force_parse(nmsp_parser_t(), "Expected a namespace.", res);
|
||||
|
||||
if (!h.curr().is_operator(operator_t::SEMICOLON)) {
|
||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
||||
}
|
||||
|
||||
out.imports.push_back(res);
|
||||
if (!h.try_advance()) return h.submit(false);
|
||||
}
|
||||
|
||||
if (!h.ended()) h.err("Invalid token.");
|
||||
|
||||
return h.submit(false);
|
||||
}
|
16
src/treeifier/constr/identifier.cc
Normal file
16
src/treeifier/constr/identifier.cc
Normal file
@ -0,0 +1,16 @@
|
||||
#include "treeifier/constr/helper.hh"
|
||||
#include "treeifier/constr/identifier.hh"
|
||||
|
||||
using namespace ppc::tree::constr;
|
||||
|
||||
bool identifier_parser_t::operator()(ast_ctx_t& ctx, size_t& res_i, located_t<std::string>& out) const {
|
||||
parse_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
if (h.curr().is_identifier()) {
|
||||
out = located_t<std::string>(h.loc(), h.curr().identifier());
|
||||
return h.submit();
|
||||
}
|
||||
else return false;
|
||||
}
|
26
src/treeifier/constr/nmsp.cc
Normal file
26
src/treeifier/constr/nmsp.cc
Normal file
@ -0,0 +1,26 @@
|
||||
#include "treeifier/constr/helper.hh"
|
||||
#include "treeifier/constr/nmsp.hh"
|
||||
|
||||
using namespace ppc::tree::constr;
|
||||
|
||||
bool nmsp_parser_t::operator()(ast_ctx_t &ctx, size_t &res_i, loc_namespace_name_t &out) const {
|
||||
parse_helper_t h(ctx, res_i);
|
||||
|
||||
if (h.ended()) return false;
|
||||
|
||||
out.clear();
|
||||
located_t<std::string> val;
|
||||
|
||||
if (!h.parse(identifier_parser_t(), val)) return false;
|
||||
else out.push_back(val);
|
||||
|
||||
while (true) {
|
||||
if (h.ended()) break;
|
||||
if (!h.curr().is_operator(operator_t::DOUBLE_COLON)) break;
|
||||
h.advance("Expected an identifier.");
|
||||
h.force_parse(identifier_parser_t(), "Expected an identifier.", val);
|
||||
out.push_back(val);
|
||||
}
|
||||
|
||||
return h.submit(false);
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
#include "compiler/treeifier/lexer.hh"
|
||||
#include "treeifier/lexer.hh"
|
||||
#include "utils/message.hh"
|
||||
#include <sstream>
|
||||
|
||||
using namespace ppc;
|
||||
using namespace ppc::messages;
|
||||
using namespace ppc::comp::tree::lex;
|
||||
using namespace ppc::tree::lex;
|
||||
|
||||
struct res_t;
|
||||
using lexlet_t = res_t (*)(char c, std::vector<char> &tok);
|
@ -1,8 +1,8 @@
|
||||
#include "compiler/treeifier/tokenizer.hh"
|
||||
#include "treeifier/tokenizer.hh"
|
||||
#include <string>
|
||||
|
||||
using namespace ppc::comp::tree;
|
||||
using namespace ppc::comp;
|
||||
using namespace ppc;
|
||||
using namespace ppc::tree;
|
||||
using namespace std::string_literals;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include "compiler/treeifier/lexer.hh"
|
||||
#include "compiler/treeifier/tokenizer.hh"
|
||||
#include "treeifier/lexer.hh"
|
||||
#include "treeifier/tokenizer.hh"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
using namespace ppc;
|
||||
using namespace messages;
|
||||
using namespace comp::tree;
|
||||
using namespace ppc::tree;
|
||||
using namespace std::string_literals;
|
||||
|
||||
static std::vector<uint8_t> parse_string(msg_stack_t &msg_stack, bool is_char, const lex::token_t &token) {
|
Loading…
Reference in New Issue
Block a user