i dont even remember bruh
This commit is contained in:
parent
ee16dfbe71
commit
a36c7e5fa7
@ -1,356 +1,364 @@
|
|||||||
#include "compiler/treeifier/ast/helper.hh"
|
#include "compiler/treeifier/ast/helper.hh"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
enum precedence_t {
|
enum precedence_t {
|
||||||
NONE,
|
NONE,
|
||||||
POSTFIX,
|
POSTFIX,
|
||||||
PREFIX,
|
PREFIX,
|
||||||
MULT,
|
MULT,
|
||||||
ADD,
|
ADD,
|
||||||
SHIFT,
|
SHIFT,
|
||||||
COMP,
|
COMP,
|
||||||
EQU,
|
EQU,
|
||||||
BIN_AND,
|
BIN_AND,
|
||||||
BIN_XOR,
|
BIN_XOR,
|
||||||
BIN_OR,
|
BIN_OR,
|
||||||
BOOL_AND,
|
BOOL_AND,
|
||||||
BOOL_OR,
|
BOOL_OR,
|
||||||
TERNARY,
|
TERNARY,
|
||||||
ASSIGN,
|
ASSIGN,
|
||||||
PAREN,
|
PAREN,
|
||||||
CALL_START,
|
CALL_START,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct op_data_t {
|
struct op_data_t {
|
||||||
precedence_t precedence;
|
precedence_t precedence;
|
||||||
size_t op_n;
|
size_t op_n;
|
||||||
std::string name;
|
std::string name;
|
||||||
bool assoc;
|
bool assoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
op_data_t sizeof_data { precedence_t::PREFIX, 1, "sizeof", true };
|
op_data_t sizeof_data { precedence_t::PREFIX, 1, "sizeof", true };
|
||||||
|
|
||||||
std::map<operator_t, op_data_t> pre_ops {
|
std::map<operator_t, op_data_t> pre_ops {
|
||||||
{ operator_t::INCREASE, { precedence_t::PREFIX, 1, "inc_pre" } },
|
{ operator_t::INCREASE, { precedence_t::PREFIX, 1, "inc_pre" } },
|
||||||
{ operator_t::DECREASE, { precedence_t::PREFIX, 1, "dec_pre" } },
|
{ operator_t::DECREASE, { precedence_t::PREFIX, 1, "dec_pre" } },
|
||||||
{ operator_t::ADD, { precedence_t::PREFIX, 1, "positive" } },
|
{ operator_t::ADD, { precedence_t::PREFIX, 1, "positive" } },
|
||||||
{ operator_t::SUBTRACT, { precedence_t::PREFIX, 1, "negative" } },
|
{ operator_t::SUBTRACT, { precedence_t::PREFIX, 1, "negative" } },
|
||||||
{ operator_t::BITWISE_NEGATIVE, { precedence_t::PREFIX, 1, "flip" } },
|
{ operator_t::BITWISE_NEGATIVE, { precedence_t::PREFIX, 1, "flip" } },
|
||||||
{ operator_t::MULTIPLY, { precedence_t::PREFIX, 1, "dereference" } },
|
{ operator_t::MULTIPLY, { precedence_t::PREFIX, 1, "dereference" } },
|
||||||
{ operator_t::AND, { precedence_t::PREFIX, 1, "reference" } },
|
{ operator_t::AND, { precedence_t::PREFIX, 1, "reference" } },
|
||||||
};
|
};
|
||||||
std::map<operator_t, op_data_t> bin_ops {
|
std::map<operator_t, op_data_t> bin_ops {
|
||||||
{ operator_t::INCREASE, { precedence_t::POSTFIX, 1, "inc_post" } },
|
{ operator_t::INCREASE, { precedence_t::POSTFIX, 1, "inc_post" } },
|
||||||
{ operator_t::DECREASE, { precedence_t::POSTFIX, 1, "dec_post" } },
|
{ operator_t::DECREASE, { precedence_t::POSTFIX, 1, "dec_post" } },
|
||||||
{ (operator_t)-1, sizeof_data },
|
{ (operator_t)-1, sizeof_data },
|
||||||
|
|
||||||
{ operator_t::ADD, { precedence_t::ADD, 2, "add" } },
|
{ operator_t::ADD, { precedence_t::ADD, 2, "add" } },
|
||||||
{ operator_t::SUBTRACT, { precedence_t::ADD, 2, "subtract" } },
|
{ operator_t::SUBTRACT, { precedence_t::ADD, 2, "subtract" } },
|
||||||
|
|
||||||
{ operator_t::MULTIPLY, { precedence_t::MULT, 2, "multiply" } },
|
{ operator_t::MULTIPLY, { precedence_t::MULT, 2, "multiply" } },
|
||||||
{ operator_t::DIVIDE, { precedence_t::MULT, 2, "divide" } },
|
{ operator_t::DIVIDE, { precedence_t::MULT, 2, "divide" } },
|
||||||
{ operator_t::MODULO, { precedence_t::MULT, 2, "modulo" } },
|
{ operator_t::MODULO, { precedence_t::MULT, 2, "modulo" } },
|
||||||
|
|
||||||
{ operator_t::SHIFT_LEFT, { precedence_t::SHIFT, 2, "shl" } },
|
{ operator_t::SHIFT_LEFT, { precedence_t::SHIFT, 2, "shl" } },
|
||||||
{ operator_t::SHIFT_RIGHT, { precedence_t::SHIFT, 2, "shr" } },
|
{ operator_t::SHIFT_RIGHT, { precedence_t::SHIFT, 2, "shr" } },
|
||||||
|
|
||||||
{ operator_t::LESS_THAN, { precedence_t::COMP, 2, "less" } },
|
{ operator_t::LESS_THAN, { precedence_t::COMP, 2, "less" } },
|
||||||
{ operator_t::LESS_THAN_EQUALS, { precedence_t::COMP, 2, "less_eq" } },
|
{ operator_t::LESS_THAN_EQUALS, { precedence_t::COMP, 2, "less_eq" } },
|
||||||
{ operator_t::GREATER_THAN, { precedence_t::COMP, 2, "great" } },
|
{ operator_t::GREATER_THAN, { precedence_t::COMP, 2, "great" } },
|
||||||
{ operator_t::GREATER_THAN_EQUALS, { precedence_t::COMP, 2, "great_eq" } },
|
{ operator_t::GREATER_THAN_EQUALS, { precedence_t::COMP, 2, "great_eq" } },
|
||||||
|
|
||||||
{ operator_t::EQUALS, { precedence_t::EQU, 2, "eq" } },
|
{ operator_t::EQUALS, { precedence_t::EQU, 2, "eq" } },
|
||||||
{ operator_t::NOT_EQUALS, { precedence_t::EQU, 2, "neq" } },
|
{ operator_t::NOT_EQUALS, { precedence_t::EQU, 2, "neq" } },
|
||||||
|
|
||||||
{ operator_t::AND, { precedence_t::BIN_AND, 2, "great_eq" } },
|
{ operator_t::AND, { precedence_t::BIN_AND, 2, "great_eq" } },
|
||||||
{ operator_t::OR, { precedence_t::BIN_OR, 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::XOR, { precedence_t::BIN_XOR, 2, "great_eq" } },
|
||||||
|
|
||||||
{ operator_t::DOUBLE_AND, { precedence_t::BOOL_AND, 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::DOUBLE_OR, { precedence_t::BOOL_OR, 2, "great_eq" } },
|
||||||
|
|
||||||
{ operator_t::ASSIGN, { precedence_t::ASSIGN, 2, "assign", true } },
|
{ operator_t::ASSIGN, { precedence_t::ASSIGN, 2, "assign", true } },
|
||||||
{ operator_t::ASSIGN_ADD, { precedence_t::ASSIGN, 2, "assign_add", 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_SUBTRACT, { precedence_t::ASSIGN, 2, "assign_subtract", true } },
|
||||||
{ operator_t::ASSIGN_MULTIPLY, { precedence_t::ASSIGN, 2, "assign_multiply", 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_DIVIDE, { precedence_t::ASSIGN, 2, "assign_divide", true } },
|
||||||
{ operator_t::ASSIGN_MODULO, { precedence_t::ASSIGN, 2, "assign_modulo", 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_LEFT, { precedence_t::ASSIGN, 2, "assign_shl", true } },
|
||||||
{ operator_t::ASSIGN_SHIFT_RIGHT, { precedence_t::ASSIGN, 2, "assign_shr", 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_XOR, { precedence_t::ASSIGN, 2, "assign_xor", true } },
|
||||||
{ operator_t::ASSIGN_AND, { precedence_t::ASSIGN, 2, "assign_and", 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_OR, { precedence_t::ASSIGN, 2, "assign_or", true } },
|
||||||
{ operator_t::ASSIGN_DOUBLE_AND, { precedence_t::ASSIGN, 2, "assign_dand", 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_DOUBLE_OR, { precedence_t::ASSIGN, 2, "assign_dor", true } },
|
||||||
{ operator_t::ASSIGN_NULL_COALESCING, { precedence_t::ASSIGN, 2, "assign_null_coal", 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) {
|
map_t op_to_map(located_t<op_data_t> op) {
|
||||||
return {
|
return {
|
||||||
{ "$_name", "$_operator" },
|
{ "$_name", "$_operator" },
|
||||||
{ "ops", array_t() },
|
{ "ops", array_t() },
|
||||||
{ "location", conv::loc_to_map(op.location) },
|
{ "location", conv::loc_to_map(op.location) },
|
||||||
{ "op", op.name },
|
{ "op", op.name },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pop(std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
bool pop(std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||||
if (op_stack.empty()) return false;
|
if (op_stack.empty()) return false;
|
||||||
|
|
||||||
auto map = op_to_map(op_stack.back());
|
auto map = op_to_map(op_stack.back());
|
||||||
auto op_n = op_stack.back().op_n;
|
auto op_n = op_stack.back().op_n;
|
||||||
auto loc = op_stack.back().location;
|
auto loc = op_stack.back().location;
|
||||||
op_stack.pop_back();
|
op_stack.pop_back();
|
||||||
|
|
||||||
if (res.size() < op_n) return false;
|
if (res.size() < op_n) return false;
|
||||||
|
|
||||||
auto &ops = map["ops"].array();
|
auto &ops = map["ops"].array();
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < op_n; i++) {
|
for (size_t i = 0; i < op_n; i++) {
|
||||||
ops.push_back(res.back());
|
ops.push_back(res.back());
|
||||||
loc = loc.intersect(conv::map_to_loc(res.back().map()["location"].string()));
|
loc = loc.intersect(conv::map_to_loc(res.back().map()["location"].string()));
|
||||||
res.pop_back();
|
res.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
map["location"] = conv::loc_to_map(loc);
|
map["location"] = conv::loc_to_map(loc);
|
||||||
|
|
||||||
std::reverse(ops.begin(), ops.end());
|
std::reverse(ops.begin(), ops.end());
|
||||||
res.push_back(map);
|
res.push_back(map);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool pop_paren(std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
bool pop_paren(std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||||
bool has_paren = false;
|
bool has_paren = false;
|
||||||
for (const auto &op : op_stack) {
|
for (const auto &op : op_stack) {
|
||||||
if (op.precedence == precedence_t::PAREN) {
|
if (op.precedence == precedence_t::PAREN) {
|
||||||
has_paren = true;
|
has_paren = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!has_paren) return false;
|
if (!has_paren) return false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (op_stack.back().precedence == precedence_t::PAREN) break;
|
if (op_stack.back().precedence == precedence_t::PAREN) break;
|
||||||
if (!pop(op_stack, res)) return false;
|
if (!pop(op_stack, res)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
op_stack.pop_back();
|
op_stack.pop_back();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool pop_call(size_t n, location_t loc, std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
bool pop_call(size_t n, location_t loc, std::vector<located_t<op_data_t>> &op_stack, array_t &res) {
|
||||||
map_t call = {
|
map_t call = {
|
||||||
{ "$_name", "$_call" },
|
{ "$_name", "$_call" },
|
||||||
};
|
};
|
||||||
|
|
||||||
array_t &args = call["args"].array({});
|
array_t &args = call["args"].array({});
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (op_stack.back().precedence == precedence_t::CALL_START) break;
|
if (op_stack.back().precedence == precedence_t::CALL_START) break;
|
||||||
if (!pop(op_stack, res)) return false;
|
if (!pop(op_stack, res)) return false;
|
||||||
}
|
}
|
||||||
loc = loc.intersect(op_stack.back().location);
|
loc = loc.intersect(op_stack.back().location);
|
||||||
op_stack.pop_back();
|
op_stack.pop_back();
|
||||||
call["location"] = conv::loc_to_map(loc);
|
call["location"] = conv::loc_to_map(loc);
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
args.push_back(res.back());
|
args.push_back(res.back());
|
||||||
res.pop_back();
|
res.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(args.begin(), args.end());
|
std::reverse(args.begin(), args.end());
|
||||||
|
|
||||||
call["func"] = res.back();
|
call["func"] = res.back();
|
||||||
res.pop_back();
|
res.pop_back();
|
||||||
res.push_back(call);
|
res.push_back(call);
|
||||||
|
|
||||||
return true;
|
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) {
|
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()) {
|
while (!op_stack.empty()) {
|
||||||
auto &back_data = op_stack.back();
|
auto &back_data = op_stack.back();
|
||||||
if (data.assoc ?
|
if (data.assoc ?
|
||||||
back_data.precedence >= data.precedence :
|
back_data.precedence >= data.precedence :
|
||||||
back_data.precedence > data.precedence
|
back_data.precedence > data.precedence
|
||||||
) break;
|
) break;
|
||||||
|
|
||||||
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast::parse_exp_var(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
bool ast::parse_exp_var(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
||||||
return ctx.parse(parse_nmsp, res_i, 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) {
|
bool ast::parse_exp_int_lit(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.curr().is_int_literal()) {
|
if (h.curr().is_int_literal()) {
|
||||||
auto &arr = out["content"].array({});
|
auto &arr = out["content"].array({});
|
||||||
for (auto b : h.curr().literal()) arr.push_back((float)b);
|
for (auto b : h.curr().literal()) arr.push_back((float)b);
|
||||||
out["location"] = conv::loc_to_map(h.loc());
|
out["location"] = conv::loc_to_map(h.loc());
|
||||||
return h.submit(true);
|
return h.submit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ast::parse_exp_str_lit(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
bool ast::parse_exp_str_lit(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.curr().is_str_literal()) {
|
if (h.curr().is_str_literal()) {
|
||||||
auto &arr = out["content"].array({});
|
auto &arr = out["content"].array({});
|
||||||
for (auto b : h.curr().literal()) arr.push_back((float)b);
|
for (auto b : h.curr().literal()) arr.push_back((float)b);
|
||||||
out["location"] = conv::loc_to_map(h.loc());
|
out["location"] = conv::loc_to_map(h.loc());
|
||||||
return h.submit(true);
|
return h.submit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast::parse_exp(ast_ctx_t &ctx, size_t &res_i, map_t &out) {
|
bool ast::parse_exp(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);
|
||||||
|
|
||||||
bool last_val = false;
|
bool last_val = false;
|
||||||
map_t val;
|
map_t val;
|
||||||
std::vector<located_t<op_data_t>> op_stack;
|
std::vector<located_t<op_data_t>> op_stack;
|
||||||
std::vector<size_t> call_args_n;
|
std::vector<size_t> call_args_n;
|
||||||
auto res = array_t();
|
auto res = array_t();
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (h.ended()) break;
|
if (h.ended()) break;
|
||||||
|
|
||||||
if (!last_val && h.curr().is_identifier("sizeof")) {
|
if (!last_val && h.curr().is_identifier("sizeof")) {
|
||||||
op_stack.push_back({ h.loc(), sizeof_data });
|
op_stack.push_back({ h.loc(), sizeof_data });
|
||||||
h.advance("Expected a value on the right side of the operator.");
|
h.advance("Expected a value on the right side of the operator.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!last_val && h.push_parse(ctx.group("$_exp_val"), res)) {
|
if (!last_val && h.push_parse(ctx.group("$_exp_val"), res)) {
|
||||||
last_val = true;
|
last_val = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (h.curr().is_operator()) {
|
if (h.curr().is_operator()) {
|
||||||
auto op = h.curr()._operator();
|
auto op = h.curr()._operator();
|
||||||
if (op == operator_t::PAREN_CLOSE && (last_val || (!op_stack.empty() && op_stack.back().precedence == precedence_t::CALL_START))) {
|
if (last_val) {
|
||||||
bool is_call = false, is_paren = false;
|
if (op == operator_t::PAREN_OPEN) {
|
||||||
|
h.advance("Expected an argument or closing parens.");
|
||||||
for (auto i = op_stack.rbegin(); i != op_stack.rend(); i++) {
|
op_stack.push_back({ h.loc(), { precedence_t::CALL_START } });
|
||||||
if (i->precedence == precedence_t::PAREN) {
|
if (h.curr().is_operator(operator_t::PAREN_CLOSE)) {
|
||||||
is_paren = true;
|
pop_call(0, h.loc(), op_stack, res);
|
||||||
break;
|
}
|
||||||
}
|
else {
|
||||||
else if (i->precedence == precedence_t::CALL_START) {
|
call_args_n.push_back(1);
|
||||||
is_call = true;
|
}
|
||||||
break;
|
last_val = false;
|
||||||
}
|
}
|
||||||
}
|
else if (op == operator_t::PAREN_CLOSE) {
|
||||||
|
bool is_call = false, is_paren = false;
|
||||||
if (is_call) pop_call(call_args_n.back(), h.loc(), op_stack, res);
|
|
||||||
else if (is_paren) pop_paren(op_stack, res);
|
for (auto i = op_stack.rbegin(); i != op_stack.rend(); i++) {
|
||||||
else break;
|
if (i->precedence == precedence_t::PAREN) {
|
||||||
|
is_paren = true;
|
||||||
if (!h.try_advance()) break;
|
break;
|
||||||
}
|
}
|
||||||
else if (last_val) {
|
else if (i->precedence == precedence_t::CALL_START) {
|
||||||
if (op == operator_t::PAREN_OPEN) {
|
is_call = true;
|
||||||
h.advance("Expected an argument.");
|
break;
|
||||||
call_args_n.push_back(0);
|
}
|
||||||
op_stack.push_back({ h.loc(), { precedence_t::CALL_START } });
|
}
|
||||||
last_val = false;
|
|
||||||
}
|
if (is_call) {
|
||||||
else if (op == operator_t::COMMA) {
|
pop_call(call_args_n.back(), h.loc(), op_stack, res);
|
||||||
if (call_args_n.size() == 0) break;
|
call_args_n.pop_back();
|
||||||
h.advance("Expected an argument.");
|
}
|
||||||
|
else if (is_paren) pop_paren(op_stack, res);
|
||||||
pop_until({ .precedence = precedence_t::CALL_START, .assoc = true }, h, op_stack, res);
|
else break;
|
||||||
call_args_n.back()++;
|
|
||||||
last_val = false;
|
if (!h.try_advance()) break;
|
||||||
}
|
}
|
||||||
else if (op == operator_t::COLON) {
|
else if (op == operator_t::COMMA) {
|
||||||
h.advance("Expected a type.");
|
if (call_args_n.size() == 0) break;
|
||||||
pop_until({ .precedence = precedence_t::PREFIX, .assoc = true }, h, op_stack, res);
|
h.advance("Expected an argument.");
|
||||||
map_t cast = {
|
|
||||||
{ "$_name", "$_cast" },
|
pop_until({ .precedence = precedence_t::CALL_START, .assoc = true }, h, op_stack, res);
|
||||||
{ "exp", res.back() },
|
call_args_n.back()++;
|
||||||
};
|
last_val = false;
|
||||||
|
}
|
||||||
res.pop_back();
|
else if (op == operator_t::COLON) {
|
||||||
h.force_parse(parse_type, "Expected a type.", cast["type"].map({}));
|
h.advance("Expected a type.");
|
||||||
cast["location"] = conv::loc_to_map(location_t::intersect(
|
pop_until({ .precedence = precedence_t::PREFIX, .assoc = true }, h, op_stack, res);
|
||||||
conv::map_to_loc(cast["exp"].map()["location"].string()),
|
map_t cast = {
|
||||||
conv::map_to_loc(cast["type"].map()["location"].string())
|
{ "$_name", "$_cast" },
|
||||||
));
|
{ "exp", res.back() },
|
||||||
res.push_back(cast);
|
};
|
||||||
}
|
|
||||||
else if (op == operator_t::DOT || op == operator_t::PTR_MEMBER) {
|
res.pop_back();
|
||||||
h.advance("Expected an identifier.");
|
h.force_parse(parse_type, "Expected a type.", cast["type"].map({}));
|
||||||
pop_until({ .precedence = precedence_t::POSTFIX, .assoc = true }, h, op_stack, res);
|
cast["location"] = conv::loc_to_map(location_t::intersect(
|
||||||
|
conv::map_to_loc(cast["exp"].map()["location"].string()),
|
||||||
map_t member_access = {
|
conv::map_to_loc(cast["type"].map()["location"].string())
|
||||||
{ "exp", res.back() },
|
));
|
||||||
{ "is_ptr", op == operator_t::PTR_MEMBER },
|
res.push_back(cast);
|
||||||
};
|
}
|
||||||
h.force_parse(parse_identifier, "Expected an identifier.", member_access["name"].map({}));
|
else if (op == operator_t::DOT || op == operator_t::PTR_MEMBER) {
|
||||||
member_access["location"] = conv::loc_to_map(
|
h.advance("Expected an identifier.");
|
||||||
conv::map_to_loc(member_access["name"].map()["location"].string()).intersect(
|
pop_until({ .precedence = precedence_t::POSTFIX, .assoc = true }, h, op_stack, res);
|
||||||
conv::map_to_loc(res.back().map()["location"].string())
|
|
||||||
)
|
map_t member_access = {
|
||||||
);
|
{ "exp", res.back() },
|
||||||
res.pop_back();
|
{ "is_ptr", op == operator_t::PTR_MEMBER },
|
||||||
res.push_back(member_access);
|
};
|
||||||
}
|
h.force_parse(parse_identifier, "Expected an identifier.", member_access["name"].map({}));
|
||||||
else if (bin_ops.find(op) != bin_ops.end()) {
|
member_access["location"] = conv::loc_to_map(
|
||||||
auto data = bin_ops[op];
|
conv::map_to_loc(member_access["name"].map()["location"].string()).intersect(
|
||||||
pop_until(data, h, op_stack, res);
|
conv::map_to_loc(res.back().map()["location"].string())
|
||||||
op_stack.push_back({ h.loc(), data });
|
)
|
||||||
|
);
|
||||||
if (data.op_n == 1) {
|
res.pop_back();
|
||||||
last_val = true;
|
res.push_back(member_access);
|
||||||
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
}
|
||||||
if (h.try_advance()) break;
|
else if (bin_ops.find(op) != bin_ops.end()) {
|
||||||
}
|
auto data = bin_ops[op];
|
||||||
else {
|
pop_until(data, h, op_stack, res);
|
||||||
last_val = false;
|
op_stack.push_back({ h.loc(), data });
|
||||||
h.advance("Expected a value on the right side of the operator.");
|
|
||||||
}
|
if (data.op_n == 1) {
|
||||||
}
|
last_val = true;
|
||||||
else break;
|
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
||||||
}
|
if (h.try_advance()) break;
|
||||||
else {
|
}
|
||||||
if (op == operator_t::PAREN_OPEN) {
|
else {
|
||||||
op_stack.push_back({ h.loc(), { precedence_t::PAREN } });
|
last_val = false;
|
||||||
h.advance("Expected a value.");
|
h.advance("Expected a value on the right side of the operator.");
|
||||||
last_val = false;
|
}
|
||||||
}
|
}
|
||||||
else if (pre_ops.find(op) != pre_ops.end()) {
|
else break;
|
||||||
op_stack.push_back({ h.loc(), pre_ops[op] });
|
}
|
||||||
h.advance("Expected a value on the right side of the operator.");
|
else {
|
||||||
}
|
if (op == operator_t::PAREN_OPEN) {
|
||||||
else break;
|
op_stack.push_back({ h.loc(), { precedence_t::PAREN } });
|
||||||
}
|
h.advance("Expected a value.");
|
||||||
continue;
|
last_val = false;
|
||||||
}
|
}
|
||||||
else break;
|
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.");
|
||||||
if (res.size() == 0) return false;
|
}
|
||||||
|
else break;
|
||||||
while (!op_stack.empty()) {
|
}
|
||||||
if (op_stack.back().precedence == precedence_t::PAREN) throw message_t::error("Unclosed paren.", op_stack.back().location);
|
continue;
|
||||||
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.");
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out = res.front().map();
|
if (res.size() == 0) return false;
|
||||||
|
|
||||||
return h.submit(false);
|
while (!op_stack.empty()) {
|
||||||
}
|
if (op_stack.back().precedence == precedence_t::PAREN) throw message_t::error("Unclosed paren.", op_stack.back().location);
|
||||||
bool ast::parse_stat_exp(ast_ctx_t &ctx, size_t &i, map_t &res) {
|
if (op_stack.back().precedence == precedence_t::CALL_START) throw message_t::error("Unclosed call.", op_stack.back().location);
|
||||||
tree_helper_t h(ctx, i);
|
if (!pop(op_stack, res)) return h.err("Expected an expression on the right side of this operator.");
|
||||||
if (!h.parse(parse_exp, res)) return false;
|
}
|
||||||
if (!h.ended() && h.curr().is_operator(operator_t::SEMICOLON)) return h.submit(true);
|
|
||||||
|
out = res.front().map();
|
||||||
ctx.messages.push(message_t::error("Expected a semicolon.", h.loc(1)));
|
|
||||||
return h.submit(false);
|
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);
|
||||||
|
}
|
||||||
|
375
src/main/main.cc
375
src/main/main.cc
@ -1,189 +1,186 @@
|
|||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
|
|
||||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
|
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_NEWLINE_AUTO_RETURN
|
#ifndef DISABLE_NEWLINE_AUTO_RETURN
|
||||||
#define DISABLE_NEWLINE_AUTO_RETURN 0x8
|
#define DISABLE_NEWLINE_AUTO_RETURN 0x8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
|
||||||
#undef ERROR
|
#undef ERROR
|
||||||
#undef INFO
|
#undef INFO
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "utils/threading.hh"
|
#include "utils/threading.hh"
|
||||||
#include "utils/strings.hh"
|
#include "utils/strings.hh"
|
||||||
#include "utils/json.hh"
|
#include "utils/json.hh"
|
||||||
#include "compiler/treeifier/lexer.hh"
|
#include "compiler/treeifier/lexer.hh"
|
||||||
#include "compiler/treeifier/tokenizer.hh"
|
#include "compiler/treeifier/tokenizer.hh"
|
||||||
#include "compiler/treeifier/ast.hh"
|
#include "compiler/treeifier/ast.hh"
|
||||||
#include "./opions.hh"
|
#include "./opions.hh"
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::size_t;
|
using std::size_t;
|
||||||
using namespace ppc;
|
using namespace ppc;
|
||||||
using namespace ppc::comp::tree;
|
using namespace ppc::comp::tree;
|
||||||
using namespace ppc::comp::tree::ast;
|
using namespace ppc::comp::tree::ast;
|
||||||
|
|
||||||
void add_flags(options::parser_t &parser) {
|
void add_flags(options::parser_t &parser) {
|
||||||
parser.add_flag({
|
parser.add_flag({
|
||||||
.name = "version",
|
.name = "version",
|
||||||
.shorthands = "v",
|
.shorthands = "v",
|
||||||
.description = "Displays version and license agreement of this binary",
|
.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) {
|
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||||
cout << "++C compiler\n"
|
cout << "++C compiler\n"
|
||||||
<< " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD
|
<< " Version: v" << PPC_VERSION_MAJOR << '.' << PPC_VERSION_MINOR << '.' << PPC_VERSION_BUILD
|
||||||
#if WINDOWS
|
#if WINDOWS
|
||||||
<< " (Windows)"
|
<< " (Windows)"
|
||||||
#elif LINUX
|
#elif LINUX
|
||||||
<< " (Linux)"
|
<< " (Linux)"
|
||||||
#endif
|
#endif
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " License: MIT Copyright (C) TopchetoEU\n";
|
<< " License: MIT Copyright (C) TopchetoEU\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
parser.add_flag({
|
parser.add_flag({
|
||||||
.name = "help",
|
.name = "help",
|
||||||
.shorthands = "h",
|
.shorthands = "h",
|
||||||
.description = "Displays a list of all flags and their meaning",
|
.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) {
|
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
||||||
cout << "Usage: ...flags ...files\n\n"
|
cout << "Usage: ...flags ...files\n\n"
|
||||||
<< "Flags and file names can be interlaced\n"
|
<< "Flags and file names can be interlaced\n"
|
||||||
<< "Flags will execute in the order they're written, then compilation begins\n\n"
|
<< "Flags will execute in the order they're written, then compilation begins\n\n"
|
||||||
<< "Flags:\n";
|
<< "Flags:\n";
|
||||||
|
|
||||||
for (const auto &flag : parser) {
|
for (const auto &flag : parser) {
|
||||||
std::stringstream buff;
|
std::stringstream buff;
|
||||||
buff << " --" << flag.name;
|
buff << " --" << flag.name;
|
||||||
|
|
||||||
if (flag.match_type) buff << "=...";
|
if (flag.match_type) buff << "=...";
|
||||||
if (flag.shorthands.size()) {
|
if (flag.shorthands.size()) {
|
||||||
buff << " (";
|
buff << " (";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (char shorthand : flag.shorthands) {
|
for (char shorthand : flag.shorthands) {
|
||||||
if (!first) buff << ",";
|
if (!first) buff << ",";
|
||||||
else first = false;
|
else first = false;
|
||||||
|
|
||||||
buff << " -";
|
buff << " -";
|
||||||
buff << std::string { shorthand };
|
buff << std::string { shorthand };
|
||||||
}
|
}
|
||||||
buff << ")";
|
buff << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
buff << " ";
|
buff << " ";
|
||||||
|
|
||||||
cout << buff.str();
|
cout << buff.str();
|
||||||
size_t n = buff.str().length();
|
size_t n = buff.str().length();
|
||||||
|
|
||||||
if (flag.description.size()) {
|
if (flag.description.size()) {
|
||||||
const size_t padding = 24;
|
const size_t padding = 24;
|
||||||
const size_t msg_width = 80 - padding;
|
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 i = 0; i < len / msg_width; i++) {
|
||||||
for (size_t j = 0; j < msg_width; j++) cout << flag.description[i * msg_width + j];
|
for (size_t j = 0; j < msg_width; j++) cout << flag.description[i * msg_width + j];
|
||||||
cout << std::endl;
|
cout << std::endl;
|
||||||
for (size_t j = 0; j < padding; j++) cout << ' ';
|
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({
|
parser.add_flag({
|
||||||
.name = "silent",
|
.name = "silent",
|
||||||
.shorthands = "qs",
|
.shorthands = "qs",
|
||||||
.description = "Doesn't display any messages, regardless of their severity",
|
.description = "Doesn't display any messages, regardless of their severity",
|
||||||
});
|
});
|
||||||
parser.add_flag({
|
parser.add_flag({
|
||||||
.name = "msg-threshold",
|
.name = "msg-threshold",
|
||||||
.description = "Sets a lower limit of messages that will print. Accepted values: 'all', 'debug', 'suggestion', 'info', 'warning', 'error', 'none'",
|
.description = "Sets a lower limit of messages that will print. Accepted values: 'all', 'debug', 'suggestion', 'info', 'warning', 'error', 'none'",
|
||||||
.match_type = options::MATCH_PREFIX,
|
.match_type = options::MATCH_PREFIX,
|
||||||
});
|
});
|
||||||
parser.add_flag({
|
parser.add_flag({
|
||||||
.name = "print-what",
|
.name = "print-what",
|
||||||
.description = "Prints a 'what?' type of message (you'll see)",
|
.description = "Prints a 'what?' type of message (you'll see)",
|
||||||
.match_type = options::MATCH_PREFIX,
|
.match_type = options::MATCH_PREFIX,
|
||||||
.execute = [](options::parser_t &parser, const std::string &option, ppc::messages::msg_stack_t &global_stack) {
|
.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."));
|
global_stack.push(messages::message_t((messages::message_t::level_t)69, "IDK LOL."));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
HANDLE handleOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE handleOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
DWORD consoleMode;
|
DWORD consoleMode;
|
||||||
GetConsoleMode(handleOut, &consoleMode);
|
GetConsoleMode(handleOut, &consoleMode);
|
||||||
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
consoleMode |= DISABLE_NEWLINE_AUTO_RETURN;
|
consoleMode |= DISABLE_NEWLINE_AUTO_RETURN;
|
||||||
SetConsoleMode(handleOut, consoleMode);
|
SetConsoleMode(handleOut, consoleMode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<std::string> args{ argv + 1, argv + argc };
|
std::vector<std::string> args{ argv + 1, argv + argc };
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
messages::msg_stack_t msg_stack;
|
messages::msg_stack_t msg_stack;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
options::parser_t parser;
|
options::parser_t parser;
|
||||||
data::map_t conf;
|
data::map_t conf;
|
||||||
add_flags(parser);
|
add_flags(parser);
|
||||||
|
|
||||||
for (const auto &arg : args) {
|
for (const auto &arg : args) {
|
||||||
if (!parser.parse(arg, msg_stack, conf)) {
|
if (!parser.parse(arg, msg_stack, conf)) {
|
||||||
files.push_back(arg);
|
files.push_back(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &file : files) {
|
for (const auto &file : files) {
|
||||||
try {
|
try {
|
||||||
std::ifstream f { file, std::ios_base::in };
|
std::ifstream f { file, std::ios_base::in };
|
||||||
auto tokens = token_t::parse_many(msg_stack, lex::token_t::parse_file(msg_stack, file, f));
|
if (!f.is_open()) throw message_t::error("The file doesn't exist.", { file });
|
||||||
auto ast = ast_ctx_t::parse(ast::parse_glob, msg_stack, tokens);
|
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;
|
|
||||||
}
|
std::cout << data::json::stringify(ast) << std::endl;
|
||||||
catch (const messages::message_t &msg) {
|
}
|
||||||
msg_stack.push(msg);
|
catch (const messages::message_t &msg) {
|
||||||
}
|
msg_stack.push(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const messages::message_t &msg) {
|
}
|
||||||
msg_stack.push(msg);
|
catch (const messages::message_t &msg) {
|
||||||
}
|
msg_stack.push(msg);
|
||||||
#ifndef PROFILE_debug
|
}
|
||||||
catch (const std::string &msg) {
|
#ifndef PROFILE_debug
|
||||||
msg_stack.push(message_t::error(msg));
|
catch (const std::string &msg) {
|
||||||
}
|
msg_stack.push(message_t::error(msg));
|
||||||
catch (...) {
|
}
|
||||||
std::cout << std::endl;
|
catch (...) {
|
||||||
msg_stack.push(message_t::error("A fatal error occurred."));
|
std::cout << std::endl;
|
||||||
}
|
msg_stack.push(message_t::error("A fatal error occurred."));
|
||||||
#endif
|
}
|
||||||
|
#endif
|
||||||
msg_stack.print(std::cout, messages::message_t::DEBUG, true);
|
|
||||||
|
msg_stack.print(std::cout, messages::message_t::DEBUG, true);
|
||||||
#ifdef PROFILE_debug
|
|
||||||
system("pause");
|
return 0;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user