Modules/Objects/private/parser/parser.cpp
2023-10-22 20:23:29 +03:00

840 lines
18 KiB
C++

#include "List.hpp"
#include "Logging.hpp"
#include "compiler/function.h"
#include "parser/parser.h"
#include <cstdlib>
#define MAX_STREAM_LENGTH 1024 * 8 * 200
#define REQUIRE(expr, desc, on_catch) \
DEBUG_BREAK(mRes.err); \
if (!(expr)) { \
mRes.err = new Error(desc, mTok.getCursorPrev().mAdvancedOffset); \
on_catch; \
return NULL; \
}
#define CHECK(expr, on_catch) \
if (!(expr)) { \
on_catch; \
return NULL; \
}
#define CHECK_ERROR(value, on_catch) \
if (mRes.err || !value) { \
on_catch; \
return NULL; \
}
using namespace tp;
using namespace obj;
using namespace BCgen;
bool Parser::Token::isAriphm() {
switch (type) {
case Token::ADD:
case Token::SUB:
case Token::DIV:
case Token::MUL: return true;
default: return false;
}
}
bool Parser::Token::isBoolean() {
switch (type) {
case Token::EQUAL:
case Token::NOT_EQUAL:
case Token::BOOL_AND:
case Token::BOOL_OR:
case Token::MORE:
case Token::LESS:
case Token::QE_OR_MORE:
case Token::QE_OR_LESS: return true;
default: return false;
}
}
Parser::Parser() {
mTok.build({
{ "\n|\t| |\r", Token::SPACE },
{ "var", Token::VAR },
{ "class", Token::CLASS_DEF },
{ "self", Token::SELF },
{ "\\{", Token::SCOPE_IN },
{ "\\}", Token::SCOPE_OUT },
{ "=", Token::ASSIGN },
{ "def", Token::DEF_FUNC },
{ "<<", Token::PRINT },
{ "if", Token::IF },
{ "else", Token::ELSE },
{ "while", Token::WHILE },
{ "\\(", Token::BRACKET_IN },
{ "\\)", Token::BRACKET_OUT },
{ ",", Token::COMMA },
{ "new", Token::NEW },
{ "\\.", Token::CHILD },
{ "return", Token::RETURN },
{ "==", Token::EQUAL },
{ "!=", Token::NOT_EQUAL },
{ ">", Token::MORE },
{ "<", Token::LESS },
{ ">=", Token::QE_OR_MORE },
{ "<=", Token::QE_OR_LESS },
{ "!", Token::BOOL_NOT },
{ "&&", Token::BOOL_AND },
{ "\\|\\|", Token::BOOL_OR },
{ "\\+", Token::ADD },
{ "\\*", Token::MUL },
{ "\\-", Token::SUB },
{ "/", Token::DIV },
{ ";", Token::STM_END },
{ "true", Token::CONST_TRUE },
{ "false", Token::CONST_FALSE },
{ "((\\-)|(\\+))?[0-9]+i?", Token::CONST_INT },
{ R"(((\-)|(\+))?([0-9]+)(\.)([0-9]*)?f?)", Token::CONST_FLOAT },
{ R"((/\*){\*-\*}*(\*/))", Token::COMMENT_BLOCK },
{ R"("{"-"}*")", Token::CONST_STRING },
{ "([a-z]|[A-Z]|_)+([a-z]|[A-Z]|[0-9]|_)*", Token::ID },
});
}
tp::String to_string(const char* stream, tp::alni len) {
tp::String out;
out.resize(len);
tp::memCopy(out.write(), stream, len);
return out;
}
Parser::Token Parser::tokRead() {
Token out;
if (!tokInputLeft()) {
Token out;
out.type = Token::NO_TOKEN;
return out;
}
auto crs_start = mTok.getCursor();
out.type = mTok.readTok();
out.token = to_string(crs_start.str(), mTok.lastTokLEn());
switch (out.type) {
case Token::CONST_FALSE: out.boolean = false; break;
case Token::CONST_TRUE: out.boolean = true; break;
case Token::CONST_INT:
{
char* p_end;
out.integer = std::strtol(out.token.read(), &p_end, 10);
DEBUG_ASSERT(out.token.read() != p_end);
break;
}
case Token::CONST_FLOAT:
{
char* p_end;
out.floating = std::strtod(out.token.read(), &p_end);
DEBUG_ASSERT(out.token.read() != p_end);
break;
}
case Token::CONST_STRING:
{
out.str = to_string(crs_start.str() + 1, mTok.lastTokLEn() - 2);
break;
}
}
return out;
}
Parser::Token Parser::tokLookup() {
auto crs = mTok.getCursor();
auto out = tokRead();
mTok.setCursor(crs);
return out;
}
bool Parser::tokInputLeft() {
auto type = mTok.lookupTok();
while (mTok.isInputLeft() && type == Token::SPACE || (type >= Token::__END__ && type <= Token::__START__)) {
mTok.skipTok();
type = mTok.lookupTok();
}
return type != Token::SOURCE_END_TOKEN;
}
void Parser::tokSkip() {
if (!tokInputLeft()) {
return;
}
mTok.skipTok();
}
Parser::Tokenizer::Cursor Parser::tokGetCursor() { return mTok.getCursor(); }
void Parser::tokSetCursor(Tokenizer::Cursor crs) { mTok.setCursor(crs); }
Expression* Parser::parseExprCompound() {
CHECK(tokRead() == Token::BRACKET_IN, {});
auto ret = parseExpr();
CHECK_ERROR(ret, {});
REQUIRE(tokRead() == Token::BRACKET_OUT, "Expected Closing Bracket", {});
return ret;
}
Expression* Parser::parseExprNEW() {
CHECK(tokRead() == Token::NEW, {});
auto name = tokRead();
REQUIRE(name == Token::ID, "Expected Identifier", {});
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected opening brackets", {});
REQUIRE(tokRead() == Token::BRACKET_OUT, "Expected closing brackets", {});
return ExprNew(name.token);
}
Expression* Parser::parseExprLOCAL() {
auto local_id_tok = tokRead();
if (local_id_tok == Token::ID) {
return ExprLocal(local_id_tok.token);
} else if (local_id_tok == Token::SELF) {
return ExprSelf();
}
return NULL;
}
Expression* Parser::parseExprCONST() {
auto tok = tokRead();
switch (tok) {
case Token::CONST_FALSE: return ExprConst(false);
case Token::CONST_TRUE: return ExprConst(true);
case Token::CONST_INT: return ExprConst(tok.integer);
case Token::CONST_FLOAT: return ExprConst(tok.floating);
case Token::CONST_STRING: return ExprConst(tok.str);
default: REQUIRE(0, "not a const Expr", {});
}
}
Expression* Parser::parseExprCHILD(Expression* prnt) {
CHECK(tokRead() == Token::CHILD, {});
auto id = tokRead();
REQUIRE(id == Token::ID, "Exprected Identifier", {});
return prnt->ExprChild(id.str);
}
Expression* Parser::parseExprCALL(Expression* prnt) {
CHECK(tokRead() == Token::BRACKET_IN, {});
List<Expression*> args;
READ_ARG:
Expression* expr = NULL;
auto tok = tokLookup();
REQUIRE(tok != Token::NO_TOKEN, "Missing Closing Bracket", {});
if (tok != Token::BRACKET_OUT) {
expr = parseExpr();
CHECK_ERROR(expr, {
for (auto arg : args) {
delete arg.data();
}
});
args.pushBack(expr);
tok = tokLookup();
if (tok == Token::COMMA) {
tokSkip();
goto READ_ARG;
} else if (tok != Token::BRACKET_OUT) {
for (auto arg : args) {
delete arg.data();
}
REQUIRE(0, "Expected A Closing Bracket", {});
}
}
tokSkip();
auto out = prnt->ExprCall({});
out->mArgs.reserve(args.length());
ualni idx = 0;
for (auto arg : args) {
out->mArgs[idx] = arg.data();
idx++;
}
return out;
}
Expression* Parser::parseExprAriphm() {
tp::InitialierList<ExprType> expessions = {
ExprType::Compound,
ExprType::NEW,
ExprType::LOCAL,
ExprType::CONST,
};
Expression* left = parseExpr(expessions);
CHECK_ERROR(left, {});
Expression* ret = NULL;
PARSE:
Expression* right = NULL;
auto tok = tokLookup();
if (tok.isAriphm()) {
tokSkip();
right = parseExpr(expessions);
if (mRes.err) {
if (ret) {
goto PRECEDENCE;
}
delete left;
return NULL;
}
} else {
CHECK(ret, { delete left; });
goto PRECEDENCE;
}
switch (tok) {
case Token::ADD: ret = ExprAriphm(left, right, OpCode::OBJ_ADD); break;
case Token::SUB: ret = ExprAriphm(left, right, OpCode::OBJ_SUB); break;
case Token::DIV: ret = ExprAriphm(left, right, OpCode::OBJ_DIV); break;
case Token::MUL: ret = ExprAriphm(left, right, OpCode::OBJ_MUL);
}
left = ret;
goto PARSE;
PRECEDENCE:
// FIXME: Not Implemented
return ret;
}
Expression* Parser::parseExprBOOLEAN() {
tp::InitialierList<ExprType> expessions = {
ExprType::Compound, ExprType::NEW, ExprType::LOCAL, ExprType::CONST, ExprType::BOOLEAN_NOT,
};
Expression* left = parseExpr(expessions);
CHECK_ERROR(left, {});
Expression* ret = NULL;
PARSE:
Expression* right = NULL;
auto tok = tokLookup();
if (tok.isBoolean()) {
tokSkip();
right = parseExpr(expessions);
if (mRes.err) {
if (ret) {
goto PRECEDENCE;
}
delete left;
return NULL;
}
} else {
CHECK(ret, { delete left; });
goto PRECEDENCE;
}
switch (tok) {
case Token::EQUAL: ret = ExprBool(left, right, OpCode::EQUAL); break;
case Token::NOT_EQUAL: ret = ExprBool(left, right, OpCode::NOT_EQUAL); break;
case Token::BOOL_AND: ret = ExprBool(left, right, OpCode::AND); break;
case Token::BOOL_OR: ret = ExprBool(left, right, OpCode::OR); break;
case Token::MORE: ret = ExprBool(left, right, OpCode::MORE); break;
case Token::LESS: ret = ExprBool(left, right, OpCode::LESS); break;
case Token::QE_OR_MORE: ret = ExprBool(left, right, OpCode::EQUAL_OR_MORE); break;
case Token::QE_OR_LESS: ret = ExprBool(left, right, OpCode::EQUAL_OR_LESS);
}
left = ret;
goto PARSE;
PRECEDENCE:
// FIXME: Not Implemented
return ret;
}
Expression* Parser::parseExprBOOLEAN_NOT() {
CHECK(tokRead() == Token::BOOL_NOT, {});
tp::InitialierList<ExprType> exprs = {
ExprType::Compound, ExprType::BOOLEAN, ExprType::Ariphm, ExprType::NEW, ExprType::LOCAL, ExprType::CONST,
};
auto out = parseExpr(exprs);
CHECK_ERROR(out, {});
return ExprBoolNot(out);
}
Expression* Parser::parseExprFUNC() {
auto op_tok = tokRead();
CHECK(op_tok == Token::ID, {});
return ExprFunc(op_tok.token);
}
// passed prnt isno longer responsability of callee
// suc : returns top level parent
// err : returns NULL
Expression* Parser::parseExprChain(Expression* prnt) {
PARSE_CHAIN:
auto tok = tokLookup();
switch (tok) {
case Token::CHILD:
{
tokRead();
auto child_id = tokRead();
REQUIRE(child_id == Token::ID, "expected an id", { delete prnt; });
prnt = prnt->ExprChild(child_id.token);
goto PARSE_CHAIN;
}
case Token::BRACKET_IN:
{
auto new_prnt = parseExprCALL(prnt);
CHECK_ERROR(new_prnt, { delete prnt; });
if (prnt->mType == Expression::Type::CHILD) {
((ExpressionChild*) prnt)->mMethod = true;
}
prnt = new_prnt;
goto PARSE_CHAIN;
}
}
return prnt;
}
Expression* Parser::parseExpr(tp::InitialierList<ExprType> expressions) {
Expression* out = NULL;
List<Error*> errors;
for (auto expr_type : expressions) {
auto crs = tokGetCursor();
switch (expr_type) {
case Parser::ExprType::BOOLEAN_NOT: out = parseExprBOOLEAN_NOT(); break;
case Parser::ExprType::BOOLEAN: out = parseExprBOOLEAN(); break;
case Parser::ExprType::Ariphm: out = parseExprAriphm(); break;
case Parser::ExprType::NEW: out = parseExprNEW(); break;
case Parser::ExprType::LOCAL: out = parseExprLOCAL(); break;
case Parser::ExprType::CONST: out = parseExprCONST(); break;
case Parser::ExprType::Compound: out = parseExprCompound(); break;
}
if (out) {
break;
}
tokSetCursor(crs);
if (mRes.err) {
errors.pushBack(mRes.err);
mRes.err = NULL;
}
}
if (out) {
// check for child expression and calls
out = parseExprChain(out);
// check errors
if (mRes.err) {
errors.pushBack(mRes.err);
mRes.err = NULL;
goto ERRORS;
}
for (auto err : errors) {
delete err.data();
}
return out;
}
ERRORS:
Error* error = NULL;
tp::alni max_advanced = 0;
for (auto err : errors) {
if (err.data()->mAdvanecedIdx && err.data()->mAdvanecedIdx > max_advanced) {
max_advanced = err.data()->mAdvanecedIdx;
error = err.data();
}
}
if (error) {
mRes.err = new Error(*error);
for (auto err : errors) {
delete err.data();
}
return NULL;
}
REQUIRE(0, "Expected and expression", {});
}
Statement* Parser::parseStmCall() {
Expression* expr = parseExpr();
CHECK_ERROR(expr, {});
REQUIRE(expr->mType == Expression::Type::CALL, "expression statement can only be function call", { delete expr; });
if (tokRead() != Token::STM_END) {
delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmIgnore(expr);
}
Statement* Parser::parseStmDefFunc() {
CHECK(tokRead() == Token::DEF_FUNC, {});
List<tp::String> args;
auto name = tokRead();
REQUIRE(name == Token::ID, "Expected an Identifier", {});
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
READ_ARG:
auto tok = tokLookup();
REQUIRE(tok != Token::NO_TOKEN, "Missing Closing Bracket", {});
if (tok == Token::ID) {
args.pushBack(tok.token);
tokSkip();
tok = tokLookup();
}
if (tok == Token::COMMA) {
tokSkip();
goto READ_ARG;
}
REQUIRE(tok == Token::BRACKET_OUT, "Expected Closing Bracket", {});
tokSkip();
auto func_def = StmDefFunc(name.token, {}, {});
func_def->mArgs.reserve(args.length());
ualni idx = 0;
for (auto iter : args) {
func_def->mArgs[idx] = iter.data();
idx++;
}
StatementScope* scope = parseScope(true);
CHECK_ERROR(scope, { delete func_def; });
func_def->mStatements.reserve(scope->mStatements.size());
idx = 0;
for (auto stm : scope->mStatements) {
func_def->mStatements[idx] = stm.data();
idx++;
}
delete scope;
return func_def;
}
Statement* Parser::parseStmDefLocal() {
CHECK(tokRead() == Token::VAR, {});
auto tok = tokRead();
REQUIRE(tok == Token::ID, "Expected an Identifier", {});
REQUIRE(tokRead() == Token::ASSIGN, "Expected an assigment", {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::STM_END) {
delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmDefLocal(tok.token, expr);
}
Statement* Parser::parseStmReturn() {
CHECK(tokRead() == Token::RETURN, {});
auto crs = tokGetCursor();
auto expr = parseExpr();
if (mRes.err) {
tokSetCursor(crs);
delete mRes.err;
mRes.err = NULL;
}
if (tokRead() != Token::STM_END) {
if (expr) delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return expr ? StmReturn(expr) : StmReturn();
}
Statement* Parser::parseStmPrint() {
CHECK(tokRead() == Token::PRINT, {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::STM_END) {
delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmPrint(expr);
}
Statement* Parser::parseStmIf() {
CHECK(tokRead() == Token::IF, {});
// single if
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::BRACKET_OUT) {
delete expr;
REQUIRE(0, "Expected Closing Bracket", {});
}
auto ontrue = parseScope(false);
CHECK_ERROR(ontrue, {});
// if-else
auto crs = tokGetCursor();
if (tokRead() == Token::ELSE) {
StatementScope* onfalse = parseScope(false);
CHECK_ERROR(onfalse, {
delete ontrue;
delete expr;
});
return StmIf(expr, ontrue, onfalse);
}
tokSetCursor(crs);
return StmIf(expr, ontrue, NULL);
}
Statement* Parser::parseStmWhile() {
CHECK(tokRead() == Token::WHILE, {});
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::BRACKET_OUT) {
delete expr;
REQUIRE(0, "Expected Closing Bracket", {});
}
auto scope = parseScope(false);
CHECK_ERROR(scope, {});
return StmWhile(expr, scope);
}
Statement* Parser::parseStmCopy() {
auto left = parseExpr();
CHECK_ERROR(left, {});
CHECK(tokRead() == Token::ASSIGN, {});
auto right = parseExpr();
CHECK_ERROR(right, { delete left; });
if (tokRead() != Token::STM_END) {
delete left;
delete right;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmCopy(left, right);
}
Statement* Parser::parseStmClassDef() {
CHECK(tokRead() == Token::CLASS_DEF, {});
auto id = tokRead();
REQUIRE(id == Token::ID, "Expected an Identifier", {});
auto scope = parseScope(true);
CHECK_ERROR(scope, {});
return StmClassDef(id.token, scope);
}
Statement* Parser::parseStm(tp::InitialierList<StmType> stm_types) {
Statement* out = NULL;
List<Error*> errors;
for (auto stm_type : stm_types) {
auto crs = tokGetCursor();
switch (stm_type) {
case StmType::DefFunc: out = parseStmDefFunc(); break;
case StmType::DefLocal: out = parseStmDefLocal(); break;
case StmType::Return: out = parseStmReturn(); break;
case StmType::Print: out = parseStmPrint(); break;
case StmType::If: out = parseStmIf(); break;
case StmType::While: out = parseStmWhile(); break;
case StmType::Copy: out = parseStmCopy(); break;
case StmType::Call: out = parseStmCall(); break;
case StmType::CLASS_DEF: out = parseStmClassDef(); break;
}
if (out) {
break;
}
tokSetCursor(crs);
if (mRes.err) {
errors.pushBack(mRes.err);
mRes.err = NULL;
}
}
if (out) {
for (auto err : errors) {
delete err.data();
}
return out;
}
Error* error = NULL;
tp::alni max_advanced = 0;
for (auto err : errors) {
if (err.data()->mAdvanecedIdx && max_advanced < err.data()->mAdvanecedIdx) {
max_advanced = err.data()->mAdvanecedIdx;
error = err.data();
}
}
if (error) {
mRes.err = new Error(*error);
for (auto err : errors) {
delete err.data();
}
return NULL;
}
REQUIRE(0, "Exprected A Statement", {});
}
StatementScope* Parser::parseScope(bool aPushToScopeStack) {
CHECK(tokRead() == Token::SCOPE_IN, {});
auto out = new StatementScope({}, aPushToScopeStack);
List<Statement*> stms;
READ_STM:
auto crs = tokGetCursor();
auto tok = tokRead();
if (tok == Token::NO_TOKEN) {
delete out;
for (auto stm : stms) {
delete stm.data();
}
REQUIRE(0, "Missing Scope Closing Bracket", {});
}
if (tok != Token::SCOPE_OUT) {
tokSetCursor(crs);
auto stm = parseStm();
CHECK_ERROR(stm, {
delete out;
for (auto stm : stms) {
delete stm.data();
}
});
stms.pushBack(stm);
goto READ_STM;
}
out->mStatements.reserve(stms.length());
ualni idx = 0;
for (auto stm : stms) {
out->mStatements[idx] = stm.data();
idx++;
}
return out;
}
Parser::Resault Parser::parse(const tp::String& oscript) {
mTok.bindSource(oscript.read());
mTok.reset();
mRes.scope = new StatementScope({}, true);
List<Statement*> stms;
do {
auto stm = parseStm();
if (mRes.err || !stm) { // catch
delete mRes.scope;
mRes.scope = NULL;
for (auto stm : stms) {
delete stm.data();
}
return mRes;
}
stms.pushBack(stm);
} while (tokInputLeft());
mRes.scope->mStatements.reserve(stms.length());
ualni idx = 0;
for (auto stm : stms) {
mRes.scope->mStatements[idx] = stm.data();
idx++;
}
return mRes;
}