i dont even remember bruh

This commit is contained in:
TopchetoEU 2022-11-24 14:25:42 +02:00
parent ee16dfbe71
commit a36c7e5fa7
2 changed files with 550 additions and 545 deletions

View File

@ -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);
}

View File

@ -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;
}