basic features added

This commit is contained in:
Ryan Ward 2020-12-05 00:59:16 -05:00
parent f884d8dcf8
commit 0bbb14dc06
10 changed files with 520 additions and 525 deletions

View File

@ -33,6 +33,7 @@ namespace dms {
tokens::token peek(); tokens::token peek();
tokens::token last(); tokens::token last();
std::vector<tokens::token> next(tokens::tokentype tk); std::vector<tokens::token> next(tokens::tokentype tk);
bool can();
bool match(tokens::tokentype t1 = tokens::none, tokens::tokentype t2 = tokens::none, tokens::tokentype t3 = tokens::none, tokens::tokentype t4 = tokens::none, tokens::tokentype t5 = tokens::none, tokens::tokentype t6 = tokens::none, tokens::tokentype t7 = tokens::none, tokens::tokentype t8 = tokens::none, tokens::tokentype t9 = tokens::none, tokens::tokentype t10 = tokens::none, tokens::tokentype t11 = tokens::none, tokens::tokentype t12 = tokens::none); bool match(tokens::tokentype t1 = tokens::none, tokens::tokentype t2 = tokens::none, tokens::tokentype t3 = tokens::none, tokens::tokentype t4 = tokens::none, tokens::tokentype t5 = tokens::none, tokens::tokentype t6 = tokens::none, tokens::tokentype t7 = tokens::none, tokens::tokentype t8 = tokens::none, tokens::tokentype t9 = tokens::none, tokens::tokentype t10 = tokens::none, tokens::tokentype t11 = tokens::none, tokens::tokentype t12 = tokens::none);
bool match(tokens::tokentype* t1 = nullptr, tokens::tokentype* t2 = nullptr, tokens::tokentype* t3 = nullptr, tokens::tokentype* t4 = nullptr, tokens::tokentype* t5 = nullptr, tokens::tokentype* t6 = nullptr, tokens::tokentype* t7 = nullptr, tokens::tokentype* t8 = nullptr, tokens::tokentype* t9 = nullptr, tokens::tokentype* t10 = nullptr, tokens::tokentype* t11 = nullptr, tokens::tokentype* t12 = nullptr); bool match(tokens::tokentype* t1 = nullptr, tokens::tokentype* t2 = nullptr, tokens::tokentype* t3 = nullptr, tokens::tokentype* t4 = nullptr, tokens::tokentype* t5 = nullptr, tokens::tokentype* t6 = nullptr, tokens::tokentype* t7 = nullptr, tokens::tokentype* t8 = nullptr, tokens::tokentype* t9 = nullptr, tokens::tokentype* t10 = nullptr, tokens::tokentype* t11 = nullptr, tokens::tokentype* t12 = nullptr);
bool hasScope(size_t tabs); bool hasScope(size_t tabs);
@ -64,7 +65,7 @@ namespace dms {
dms_state* state = nullptr; dms_state* state = nullptr;
void doCheck(passer* stream, std::vector<tokens::token>* t_vec, size_t line, bool& isNum, bool& hasDec, std::vector<uint8_t>* buffer); void doCheck(passer* stream, std::vector<tokens::token>* t_vec, size_t line, bool& isNum, bool& hasDec, std::vector<uint8_t>* buffer);
void _Parse(tokenstream* stream); void _Parse(tokenstream* stream);
void ParseLoop(tokenstream* stream); bool ParseLoop(tokenstream* stream, size_t count=0);
std::stack<std::string> lastCall; std::stack<std::string> lastCall;
// Match Process Code // Match Process Code
bool match_process_debug(tokenstream* stream); bool match_process_debug(tokenstream* stream);
@ -88,6 +89,9 @@ namespace dms {
bool match_process_andor(tokenstream* stream,value& v); bool match_process_andor(tokenstream* stream,value& v);
bool match_process_scope(tokenstream* stream); bool match_process_scope(tokenstream* stream);
bool match_process_while(tokenstream* stream); bool match_process_while(tokenstream* stream);
bool match_process_for(tokenstream* stream);
bool match_process_number(tokenstream* stream, value& v);
bool match_process_asm(tokenstream* stream);
// Build // Build
void buildGoto(std::string g, bool v = false); void buildGoto(std::string g, bool v = false);
@ -96,10 +100,12 @@ namespace dms {
void buildLabel(std::string l); void buildLabel(std::string l);
void buildSpeed(double s); void buildSpeed(double s);
void buildWait(double w); void buildWait(double w);
void buildCmd(codes::op,std::vector<value>);
// Utils // Utils
std::string random_string(std::size_t length); std::string random_string(std::size_t length);
bool manageCount(bool cond, size_t c,size_t&);
bool notBalanced(std::vector<tokens::token> ts, size_t last_line, tokenstream* stream, std::string o, std::string c); bool notBalanced(std::vector<tokens::token> ts, size_t last_line, tokenstream* stream, std::string o, std::string c);
void badSymbol(errors::errortype err, tokenstream* stream); void badSymbol(errors::errortype err, tokenstream* stream);
void badSymbol(tokenstream* stream); void badSymbol(tokenstream* stream);

View File

@ -48,4 +48,11 @@ namespace dms {
c->args.push(value(w)); c->args.push(value(w));
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
void LineParser::buildCmd(codes::op op, std::vector<value> args)
{
cmd* c = new cmd;
c->opcode = op;
c->args.args = args;
current_chunk->addCmd(c);
}
} }

View File

@ -5,7 +5,7 @@ using namespace dms::utils;
namespace dms { namespace dms {
bool LineParser::match_process_standard(tokenstream* stream, value& v) { bool LineParser::match_process_standard(tokenstream* stream, value& v) {
stream->chomp(newline); stream->chomp(newline);
//utils::debug(stream->peek()); utils::debug(stream->peek());
if (stream->peek().type == tokens::none) { if (stream->peek().type == tokens::none) {
return false; return false;
} }
@ -73,10 +73,6 @@ namespace dms {
} }
return true; return true;
} }
if (match_process_andor(stream, v)) {
match_process_condition(stream, v);
return true;
}
if (match_process_expression(stream, v)) { if (match_process_expression(stream, v)) {
match_process_condition(stream,v); match_process_condition(stream,v);
return true; return true;
@ -105,8 +101,7 @@ namespace dms {
match_process_condition(stream, v); match_process_condition(stream, v);
return true; return true;
} }
else if (stream->match(tokens::number)) { else if (match_process_number(stream, v)) {
v.set(std::stod(stream->next().name));
match_process_condition(stream, v); match_process_condition(stream, v);
return true; return true;
} }
@ -139,6 +134,9 @@ namespace dms {
else if (stream->match(tokens::newline)) { else if (stream->match(tokens::newline)) {
stream->next(); stream->next();
return match_process_standard(stream,v); return match_process_standard(stream,v);
} else if (match_process_andor(stream, v)) {
match_process_condition(stream, v);
return true;
} }
return false; return false;
} }
@ -212,7 +210,7 @@ namespace dms {
stream->next(); stream->next();
} }
else { else {
return match_process_andor(stream,v); return false;
} }
// So if all is good we continue here // So if all is good we continue here
value right = value(datatypes::variable); value right = value(datatypes::variable);
@ -459,7 +457,7 @@ namespace dms {
} }
bool LineParser::match_process_return(tokenstream* stream) { bool LineParser::match_process_return(tokenstream* stream) {
// Only handle this inside of a function block! // Only handle this inside of a function block!
if (current_chunk->type == blocktype::bt_method) { if (current_chunk->type == bt_method) {
if (stream->match(tokens::ret)) { if (stream->match(tokens::ret)) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::RETN; c->opcode = codes::RETN;
@ -937,6 +935,9 @@ namespace dms {
ParseLoop(&tempstream); // Done ParseLoop(&tempstream); // Done
return true; return true;
} }
else if (ParseLoop(stream, 1)) {
return true; // Let's try and match one command
}
return false; return false;
} }
bool LineParser::match_process_while(tokenstream* stream) bool LineParser::match_process_while(tokenstream* stream)
@ -948,7 +949,15 @@ namespace dms {
std::string wstart = std::string("WHS_") + random_string(4); std::string wstart = std::string("WHS_") + random_string(4);
std::string wend = std::string("WHE_") + random_string(4); std::string wend = std::string("WHE_") + random_string(4);
buildLabel(wstart); buildLabel(wstart);
if (stream->match(parao) && match_process_standard(stream,ref)) {
if (stream->match(parao)) {
size_t last_line = stream->last().line_num;
std::vector<token> t = stream->next(parao, parac); // Consume and get tokens
t.pop_back();
tokenstream tempstream(&t);
if (notBalanced(t, last_line, stream, "(", ")"))
return false;
if (match_process_standard(&tempstream, ref)) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::IFFF; c->opcode = codes::IFFF;
c->args.push(ref); c->args.push(ref);
@ -968,8 +977,283 @@ namespace dms {
return false; return false;
} }
} }
}
return false; return false;
} }
bool LineParser::match_process_for(tokenstream* stream)
{
if (stream->match(tokens::name) && stream->peek().name == "for") {
stream->next();
stream->chomp(tokens::newline);
value ref(datatypes::variable);
std::string fstart = std::string("FOS_") + random_string(4);
std::string fend = std::string("FOE_") + random_string(4);
if (stream->match(parao)) {
size_t last_line = stream->last().line_num;
std::vector<token> t = stream->next(tokens::parao, tokens::parac); // Consume and get tokens
if (notBalanced(t, last_line, stream, "(", ")"))
return false;
t.pop_back();
tokenstream tempstream(&t);
cmd* c = new cmd;
int count = 0;
value iter;
value start;
value end;
value inc = value(1);
if (tempstream.match(tokens::name,tokens::equal)) {
std::vector<token> assn = tempstream.next(tokens::seperator);
assn.pop_back(); // That comma gets consumed
tokenstream tstream(&assn);
if (ParseLoop(&tstream, 1)) {
// Grab the values from the parseloop
cmd* tempc = current_chunk->cmds.back();
iter = tempc->args.args[0];
start = tempc->args.args[1];
buildLabel(fstart); // Now that we assigned we can build the lael
if (match_process_standard(&tempstream, end)) {
// Set end to the value it needs to be
if (tempstream.match(tokens::seperator)) {
tempstream.next();
if (match_process_standard(&tempstream, inc)) {
// If this works then we got all the needed values
goto for_ack_done; // Skip all the checks from the nested if statements
}
else {
badSymbol(&tempstream);
}
}
}
else {
badSymbol(&tempstream);
return false;
}
}
else {
badSymbol(&tstream);
return false;
}
}
else {
badSymbol(&tempstream);
return false;
}
// Now we build the rest of the bytecode
for_ack_done:
value co = value(variable);
int com;
if (start > end) // counting up
com = comp::gteq;
else // counting down
com = comp::lteq;
buildCmd(codes::COMP, { value(com), co, iter, end });
buildCmd(codes::IFFF, { co, value(fend) });
if (match_process_scope(stream)) {
buildCmd(codes::ADD, {iter,inc,iter});
buildGoto(fstart);
buildLabel(fend);
return true;
}
else {
badSymbol(stream);
}
}
}
return false;
}
bool LineParser::match_process_number(tokenstream* stream, value& v)
{
if (stream->match(tokens::number)) {
v.set(std::stod(stream->next().name));
v.type = datatypes::number;
return true;
}
else if (stream->match(tokens::minus, tokens::number)) {
stream->next();
v.set(-std::stod(stream->next().name));
v.type = datatypes::number;
return true;
}
return false;
}
bool LineParser::match_process_asm(tokenstream* stream)
{
if (stream->match(tokens::name) && stream->peek().name == "asm") {
stream->next();
stream->chomp(tokens::newline);
if (stream->match(tokens::cbracketo)) {
size_t last_line = stream->last().line_num;
std::vector<token> t = stream->next(tokens::cbracketo, tokens::cbracketc); // Consume and get tokens
if (notBalanced(t, last_line, stream, "{", "}"))
return false;
t.pop_back();
tokenstream ts(&t);
std::vector<value> temp;
codes::op o;
while (ts.can()) {
utils::debug(ts.peek());
if (ts.match(tokens::string)) {
temp.push_back(value(ts.next().name));
}
else if (ts.match(tokens::number)) {
temp.push_back(value(std::stod(ts.next().name)));
}
else if (ts.match(tokens::minus,tokens::number)) {
ts.next();
temp.push_back(value(-std::stod(ts.next().name)));
}
else if (ts.match(tokens::True)) {
temp.push_back(value(true));
}
else if (ts.match(tokens::False)) {
temp.push_back(value(false));
}
else if (ts.match(tokens::bracketo, tokens::name, tokens::bracketc)) {
ts.next();
temp.push_back(value(ts.next().name,block));
ts.next();
}
else if (ts.match(tokens::percent, tokens::name)) {
ts.next();
temp.push_back(value(ts.next().name,variable));
}
else if (ts.match(tokens::newline)) {
ts.next();
}
else if (ts.match(tokens::nil)) {
temp.push_back(value());
ts.next();
}
else if (ts.match(tokens::name)) {
if (temp.size() >= 1) {
buildCmd(o, temp);
}
temp.clear();
std::string cmd = ts.next().name;
tolower(cmd);
if (cmd == "noop")
o = codes::NOOP;
else if (cmd == "entr")
o = codes::ENTR;
else if (cmd == "enab")
o = codes::ENAB;
else if (cmd == "disa")
o = codes::DISA;
else if (cmd == "load")
o = codes::LOAD;
else if (cmd == "vern")
o = codes::VERN;
else if (cmd == "usin")
o = codes::USIN;
else if (cmd == "stat")
o = codes::STAT;
else if (cmd == "disp")
o = codes::DISP;
else if (cmd == "asgn")
o = codes::ASGN;
else if (cmd == "labl")
o = codes::LABL;
else if (cmd == "choi")
o = codes::CHOI;
else if (cmd == "blck")
o = codes::BLCK;
else if (cmd == "fore")
o = codes::FORE;
else if (cmd == "whle")
o = codes::WHLE;
else if (cmd == "func")
o = codes::FUNC;
else if (cmd == "ifff")
o = codes::IFFF;
else if (cmd == "knot")
o = codes::KNOT;
else if (cmd == "else")
o = codes::ELSE;
else if (cmd == "defn")
o = codes::DEFN;
else if (cmd == "skip")
o = codes::SKIP;
else if (cmd == "comp")
o = codes::COMP;
else if (cmd == "indx")
o = codes::INDX;
else if (cmd == "inst")
o = codes::INST;
else if (cmd == "erro")
o = codes::ERRO;
else if (cmd == "goto")
o = codes::GOTO;
else if (cmd == "jump")
o = codes::JUMP;
else if (cmd == "retn")
o = codes::RETN;
else if (cmd == "exit")
o = codes::EXIT;
else if (cmd == "debg")
o = codes::DEBG;
else if (cmd == "dspd")
o = codes::DSPD;
else if (cmd == "dact")
o = codes::DACT;
else if (cmd == "wait")
o = codes::WAIT;
else if (cmd == "apnd")
o = codes::APND;
else if (cmd == "sspk")
o = codes::SSPK;
else if (cmd == "add")
o = codes::ADD;
else if (cmd == "sub")
o = codes::SUB;
else if (cmd == "mul")
o = codes::MUL;
else if (cmd == "div")
o = codes::DIV;
else if (cmd == "pow")
o = codes::POW;
else if (cmd == "mod")
o = codes::MOD;
else if (cmd == "list")
o = codes::LIST;
else if (cmd == "line")
o = codes::LINE;
else if (cmd == "halt")
o = codes::HALT;
else if (cmd == "file")
o = codes::FILE;
else if (cmd == "gc")
o = codes::GC;
else if (cmd == "asid")
o = codes::ASID;
else if (cmd == "ofun")
o = codes::OFUN;
}
else {
badSymbol(&ts);
}
}
if (temp.size() >= 1) {
buildCmd(o, temp);
}
return true;
}
}
return false;
}
/*
stream->match(tokens::bracketo, tokens::name, tokens::bracketc)) {
// We are assigning a block as a variable
stream->next();
v.set(stream->next().name);
v.type = datatypes::block;
stream->next();
match_process_condition(stream, v);
return true;
*/
bool LineParser::match_process_IFFF(tokenstream* stream) { bool LineParser::match_process_IFFF(tokenstream* stream) {
/*if(this) { /*if(this) {
* then() * then()
@ -997,32 +1281,38 @@ namespace dms {
if (match_process_standard(&tmpstream,cmp)) { if (match_process_standard(&tmpstream,cmp)) {
std::string ifend = std::string("IFE_") + random_string(4); std::string ifend = std::string("IFE_") + random_string(4);
std::string next = std::string("IFF_") + random_string(4); std::string next = std::string("IFF_") + random_string(4);
if (stream->match(tokens::cbracketo)) { cmd* c = new cmd;
size_t last_line = stream->last().line_num; c->opcode = codes::IFFF;
c->args.push(cmp);
c->args.push(value(next));
current_chunk->addCmd(c);
if (match_process_scope(stream)) {
/*size_t last_line = stream->last().line_num;
std::vector<token> toks = stream->next(tokens::cbracketo, tokens::cbracketc); std::vector<token> toks = stream->next(tokens::cbracketo, tokens::cbracketc);
if (notBalanced(toks, last_line, stream, "{", "}")) if (notBalanced(toks, last_line, stream, "{", "}"))
return false; return false;
toks.pop_back(); toks.pop_back();
tokenstream tempstream(&toks); tokenstream tempstream(&toks);
cmd* c = new cmd; ParseLoop(&tempstream);*/
c->opcode = codes::IFFF;
c->args.push(cmp);
c->args.push(value(next));
current_chunk->addCmd(c);
ParseLoop(&tempstream);
buildGoto(ifend); buildGoto(ifend);
buildLabel(next); buildLabel(next);
if (match_process_ELIF(stream,ifend) || match_process_ELSE(stream, ifend)) {} stream->chomp(newline);
if (match_process_ELIF(stream, ifend) || match_process_ELSE(stream, ifend)) {
}
else if (stream->match(tokens::pipe)) {
stream->next();
stream->chomp(newline);
if (!match_process_scope(stream)) {
state->push_error(errors::error{ errors::unknown,"Missing else function or scope",true,stream->peek().line_num,current_chunk });
return false;
}
}
buildLabel(ifend); buildLabel(ifend);
// We keep trying to match else if/else until nothing is left // We keep trying to match else if/else until nothing is left
return true; return true;
} }
else if (stream->match(tokens::name,tokens::parao)) { else if (stream->match(tokens::name,tokens::parao)) {
cmd* c = new cmd;
c->opcode = codes::IFFF;
c->args.push(cmp);
c->args.push(value(next));
current_chunk->addCmd(c);
if (match_process_function(stream, nil)) { if (match_process_function(stream, nil)) {
stream->chomp(newline); stream->chomp(newline);
if (stream->match(tokens::pipe)) { if (stream->match(tokens::pipe)) {
@ -1057,17 +1347,12 @@ namespace dms {
return false; // TODO finish this return false; // TODO finish this
} }
bool LineParser::match_process_ELSE(tokenstream* stream, std::string ifend) { bool LineParser::match_process_ELSE(tokenstream* stream, std::string ifend) {
if (stream->match(tokens::name, tokens::cbracketo) && stream->peek().name == "else") { if (stream->match(tokens::name) && stream->peek().name == "else") {
stream->next(); stream->next();
size_t last_line = stream->last().line_num; if (match_process_scope(stream)) {
std::vector<token> ts = stream->next(tokens::cbracketo, tokens::cbracketc);
if (notBalanced(ts, last_line, stream, "{", "}"))
return false;
ts.pop_back();
tokenstream tempstream(&ts);
ParseLoop(&tempstream);
return true; return true;
} }
}
return false; return false;
} }
bool LineParser::match_process_ELIF(tokenstream* stream, std::string ifend) { bool LineParser::match_process_ELIF(tokenstream* stream, std::string ifend) {
@ -1083,22 +1368,31 @@ namespace dms {
//buildLabel(iff); //buildLabel(iff);
if (match_process_standard(&tmpstream, cmp)) { if (match_process_standard(&tmpstream, cmp)) {
std::string next = std::string("IFF_") + random_string(4); std::string next = std::string("IFF_") + random_string(4);
if (stream->match(tokens::cbracketo)) { if (match_process_scope(stream)) {
size_t last_line = stream->last().line_num; /*size_t last_line = stream->last().line_num;
std::vector<token> toks = stream->next(tokens::cbracketo, tokens::cbracketc); std::vector<token> toks = stream->next(tokens::cbracketo, tokens::cbracketc);
if (notBalanced(ts, last_line, stream, "{", "}")) if (notBalanced(ts, last_line, stream, "{", "}"))
return false; return false;
toks.pop_back(); toks.pop_back();
tokenstream tempstream(&toks); tokenstream tempstream(&toks);*/
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::IFFF; c->opcode = codes::IFFF;
c->args.push(cmp); c->args.push(cmp);
c->args.push(value(next)); c->args.push(value(next));
current_chunk->addCmd(c); current_chunk->addCmd(c);
ParseLoop(&tempstream); //ParseLoop(&tempstream);
buildGoto(ifend); buildGoto(ifend);
buildLabel(next); buildLabel(next);
stream->chomp(newline);
if (match_process_ELIF(stream, ifend) || match_process_ELSE(stream, ifend)) {} if (match_process_ELIF(stream, ifend) || match_process_ELSE(stream, ifend)) {}
else if (stream->match(tokens::pipe)) {
stream->next();
stream->chomp(newline);
if (!match_process_scope(stream)) {
state->push_error(errors::error{ errors::unknown,"Missing else function or scope",true,stream->peek().line_num,current_chunk });
return false;
}
}
// We keep trying to match else if/else until nothing is left // We keep trying to match else if/else until nothing is left
return true; return true;
} }
@ -1134,13 +1428,13 @@ namespace dms {
stream->store(current_chunk); stream->store(current_chunk);
cmd* lastcmd = nullptr; cmd* lastcmd = nullptr;
// It has to start with one of these 3 to even be considered an expression // It has to start with one of these 3 to even be considered an expression
if ((stream->match(tokens::number) || stream->match(tokens::string) || stream->match(tokens::name) || stream->match(tokens::parao)) && stream->tokens.size()>=3) { if ((stream->match(tokens::minus,tokens::number) || stream->match(tokens::number) || stream->match(tokens::string) || stream->match(tokens::name) || stream->match(tokens::parao)) && stream->tokens.size()>=3) {
// What do we know, math expressions can only be on a single line. We know where to stop looking if we have to // What do we know, math expressions can only be on a single line. We know where to stop looking if we have to
cmd* c = new cmd; cmd* c = new cmd;
value wv; value wv;
value left; // lefthand value left; // left hand
codes::op op; // opperator codes::op op; // opperator
value right; // righthand value right; // right hand
reset(left, op, right); reset(left, op, right);
size_t loops = 0; size_t loops = 0;
bool hasOP = false; bool hasOP = false;

View File

@ -342,13 +342,14 @@ namespace dms {
outputFile.close(); outputFile.close();
} }
} }
void LineParser::ParseLoop(tokenstream* stream) { bool LineParser::ParseLoop(tokenstream* stream, size_t count) {
if (stop) return; if (stop) return false;
token current = stream->next(); size_t current_count=0;
token current = token{tokentype::newline,codes::NOOP};
cmd* flagcmd = new cmd; cmd* flagcmd = new cmd;
value nil; value nil;
while (stream->peek().type != tokens::none) { while (stream->peek().type != tokens::none) {
if (stop) return; if (stop) return false;
debugInvoker(stream); debugInvoker(stream);
//utils::debug(current); //utils::debug(current);
//utils::print("[flags]"); //utils::print("[flags]");
@ -372,7 +373,7 @@ namespace dms {
else if (code == codes::ENTR && tok == tokens::name) { else if (code == codes::ENTR && tok == tokens::name) {
if (state->entry != "$undefined") { if (state->entry != "$undefined") {
state->push_error(errors::error{ errors::unknown ,utils::concat("Entrypoint already defined as '",state->entry,"'. Trying to redefine as '",temp[0].name,"' is not allowed!"), true,stream->last().line_num,current_chunk }); state->push_error(errors::error{ errors::unknown ,utils::concat("Entrypoint already defined as '",state->entry,"'. Trying to redefine as '",temp[0].name,"' is not allowed!"), true,stream->last().line_num,current_chunk });
return; return false;
} }
state->entry = temp[0].name; state->entry = temp[0].name;
flagcmd->opcode = code; flagcmd->opcode = code;
@ -408,20 +409,18 @@ namespace dms {
} }
else { else {
state->push_error(errors::error{ errors::badtoken,concat("Expected <FLAG IDENTIFIER> got: ", current, temp[0]),true,line,current_chunk }); state->push_error(errors::error{ errors::badtoken,concat("Expected <FLAG IDENTIFIER> got: ", current, temp[0]),true,line,current_chunk });
return; return false;
} }
} }
// Default block // Default block
if (stream->match(tokens::newline, tokens::bracketo, tokens::name, tokens::bracketc, tokens::newline)) { if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc, tokens::newline)) {
stream->next();
stream->next(); stream->next();
std::string name = stream->next().name; std::string name = stream->next().name;
createBlock(name, bt_block); createBlock(name, bt_block);
line = stream->next().line_num; // Consume line = stream->next().line_num; // Consume
} }
// This handles a few block types since they all follow a similar format // This handles a few block types since they all follow a similar format
else if (stream->match(tokens::newline, tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::bracketc)) { else if (stream->match(tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::bracketc)) {
stream->next();
stream->next(); stream->next();
std::string name = stream->next().name; std::string name = stream->next().name;
line = stream->next().line_num; line = stream->next().line_num;
@ -441,10 +440,9 @@ namespace dms {
stream->next(); stream->next();
} }
// Function block type // Function block type
else if (stream->match(tokens::newline, tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::parao)) { else if (stream->match(tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::parao)) {
std::stringstream str; std::stringstream str;
stream->next(); stream->next();
stream->next();
std::string name = stream->next().name; std::string name = stream->next().name;
line = stream->next().line_num; // The color, not needed after the inital match, but we still need to consume it line = stream->next().line_num; // The color, not needed after the inital match, but we still need to consume it
std::string b = stream->next().name; std::string b = stream->next().name;
@ -470,58 +468,69 @@ namespace dms {
str << "Unexpected symbol: " << tokens[i]; str << "Unexpected symbol: " << tokens[i];
state->push_error(errors::error{ errors::badtoken,str.str(),true,line,current_chunk }); state->push_error(errors::error{ errors::badtoken,str.str(),true,line,current_chunk });
return; return false;
} }
} }
// If all went well the 'args' now has all of tha params for the method we will be working with // If all went well the 'args' now has all of tha params for the method we will be working with
current_chunk->params = args; current_chunk->params = args;
// Thats should be all we need to do // Thats should be all we need to do
if (stream->peek().type != tokens::bracketc) {
state->push_error(errors::error{ errors::badtoken, "Incomplete function block declaration! Expected ']' to close the block!",true,line,current_chunk });
return false;
}
else {
stream->next(); stream->next();
} }
}
else { else {
str << "'function' keyword expected got " << b; str << "'function' keyword expected got " << b;
state->push_error(errors::error{ errors::badtoken, str.str(),true,line,current_chunk }); state->push_error(errors::error{ errors::badtoken, str.str(),true,line,current_chunk });
return; return false;
} }
} }
// Control Handle all controls here // Control Handle all controls here
match_process_while(stream); manageCount(match_process_while(stream),count,current_count);
match_process_IFFF(stream); manageCount(match_process_for(stream), count, current_count);
manageCount(match_process_IFFF(stream), count, current_count);
// Let's handle function stuff! // Let's handle function stuff!
//utils::print("[return]"); //utils::print("[return]");
match_process_return(stream); manageCount(match_process_return(stream), count, current_count);
//utils::print("[disp]"); //utils::print("[disp]");
match_process_disp(stream); // Match and process dialogue manageCount(match_process_disp(stream), count, current_count); // Match and process dialogue
//utils::print("[label]"); //utils::print("[label]");
if (stream->match(tokens::newline, tokens::label)) { // Match and process labels if (stream->match(tokens::newline, tokens::label)) { // Match and process labels
stream->next(); stream->next();// We don't add this to the count, since a label is just a position to jump to!
buildLabel(stream->next().name); buildLabel(stream->next().name);
} }
//utils::print("[func]"); //utils::print("[func]");
match_process_function(stream, nil); // Naked Function manageCount(match_process_function(stream, nil), count, current_count); // Naked Function
//utils::print("[assn]"); //utils::print("[assn]");
match_process_assignment(stream); manageCount(match_process_assignment(stream), count, current_count);
//utils::print("[debug]"); //utils::print("[debug]");
match_process_debug(stream); manageCount(match_process_debug(stream), count, current_count);
//utils::print("[goto]"); //utils::print("[goto]");
match_process_goto(stream); manageCount(match_process_goto(stream), count, current_count);
//utils::print("[exit]"); //utils::print("[exit]");
match_process_exit(stream); manageCount(match_process_exit(stream), count, current_count);
//utils::print("[wait]"); //utils::print("[wait]");
match_process_wait(stream); manageCount(match_process_wait(stream), count, current_count);
//utils::print("[jump]"); //utils::print("[jump]");
match_process_jump(stream); manageCount(match_process_jump(stream), count, current_count);
manageCount(match_process_asm(stream), count, current_count);
if (count != 0 && current_count == count) {
return true; // We got what we came for, we exit and consume no more!
}
if(stream->match(newline) || stream->match(eof)) if(stream->match(newline) || stream->match(eof))
current = stream->next(); current = stream->next();
//utils::debug(stream->peek()); utils::debug(stream->peek());
} }
} }
void LineParser::_Parse(tokenstream* stream) { void LineParser::_Parse(tokenstream* stream) {
if (stop) return; if (stop) return;
createBlock("$INIT", blocktype::bt_block); createBlock("$INIT", bt_block);
ParseLoop(stream); ParseLoop(stream);
if (stop) return; if (stop) return;
createBlock("$END", blocktype::bt_block);// Runs code that ensures that last user block is processed into the chunks array. Yes, I could have simply added in the lines of code at the end, but I didn't want to rewrite code again! createBlock("$END", bt_block);// Runs code that ensures that last user block is processed into the chunks array. Yes, I could have simply added in the lines of code at the end, but I didn't want to rewrite code again!
} }
} }

View File

@ -94,6 +94,10 @@ namespace dms {
temp.push_back(next()); temp.push_back(next());
return temp; return temp;
} }
bool tokenstream::can()
{
return peek().type != tokens::none;
}
uint8_t passer::next() { uint8_t passer::next() {
if (stream.size() == pos) { if (stream.size() == pos) {
return NULL; return NULL;
@ -141,6 +145,14 @@ namespace dms {
return random_string; return random_string;
} }
bool LineParser::manageCount(bool cond, size_t c, size_t& count)
{
if (cond && c!=0) {
count++;
return true;
}
return false;
}
bool LineParser::notBalanced(std::vector<tokens::token> ts, size_t last_line, tokenstream* stream, std::string o, std::string c) { bool LineParser::notBalanced(std::vector<tokens::token> ts, size_t last_line, tokenstream* stream, std::string o, std::string c) {
if (ts.size() == 0) { if (ts.size() == 0) {
stop = true; stop = true;

View File

@ -7,14 +7,14 @@ namespace dms {
init_init = true; init_init = true;
cmd* c = new cmd; cmd* c = new cmd;
for (const auto& [key, val] : chunks) { for (const auto& [key, val] : chunks) {
if (val->type == blocktype::bt_character || val->type == blocktype::bt_env) { if (val->type == bt_character || val->type == bt_env) {
c->opcode = codes::ASGN; c->opcode = codes::ASGN;
c->args.push(value(key, datatypes::variable)); c->args.push(value(key, datatypes::variable));
c->args.push(value(key, datatypes::block)); c->args.push(value(key, datatypes::block));
chunks["$INIT"]->addCmd(c); chunks["$INIT"]->addCmd(c);
c = new cmd; c = new cmd;
} }
else if (val->type == blocktype::bt_method) { else if (val->type == bt_method) {
c->opcode = codes::RETN; c->opcode = codes::RETN;
c->args.push(value()); c->args.push(value());
val->addCmd(c); val->addCmd(c);
@ -95,13 +95,13 @@ namespace dms {
return true; return true;
} }
bool dms_state::characterExists(std::string bk_name) { bool dms_state::characterExists(std::string bk_name) {
return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_character); return (chunks.count(bk_name) && chunks[bk_name]->type == bt_character);
} }
bool dms_state::environmentExists(std::string bk_name) { bool dms_state::environmentExists(std::string bk_name) {
return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_env); return (chunks.count(bk_name) && chunks[bk_name]->type == bt_env);
} }
bool dms_state::functionExists(std::string bk_name) { bool dms_state::functionExists(std::string bk_name) {
return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_method); return (chunks.count(bk_name) && chunks[bk_name]->type == bt_method);
} }
bool dms_state::blockExists(std::string bk_name) { bool dms_state::blockExists(std::string bk_name) {
return (chunks.count(bk_name)); return (chunks.count(bk_name));

Binary file not shown.

View File

@ -22,9 +22,6 @@ Line <6> newline
Line <6> newline Line <6> newline
Line <7> newline Line <7> newline
Line <8> newline Line <8> newline
Line <9> flag
Line <9> string loadtest.dms
Line <9> newline
Line <9> newline Line <9> newline
Line <10> flag Line <10> flag
Line <10> number 0.2 Line <10> number 0.2
@ -39,467 +36,172 @@ Line <12> name main
Line <12> bracketc ] Line <12> bracketc ]
Line <12> newline Line <12> newline
Line <12> newline Line <12> newline
Line <13> name a1 Line <13> name a
Line <13> equal = Line <13> equal =
Line <13> number 10 Line <13> number 0
Line <13> newline Line <13> newline
Line <13> newline Line <13> newline
Line <14> name b1 Line <14> name while
Line <14> equal = Line <14> parao (
Line <14> number 15 Line <14> true true
Line <14> parac )
Line <14> newline Line <14> newline
Line <14> newline Line <14> newline
Line <15> name print Line <15> name asm
Line <15> parao ( Line <15> cbracketo {
Line <15> string this
Line <15> plus +
Line <15> string or
Line <15> plus +
Line <15> string that
Line <15> parac )
Line <15> newline Line <15> newline
Line <15> newline Line <15> newline
Line <16> name add
Line <16> mod %
Line <16> name a
Line <16> mod %
Line <16> name a
Line <16> number 1
Line <16> newline Line <16> newline
Line <16> newline Line <16> newline
Line <17> name if Line <17> name func
Line <17> parao ( Line <17> mod %
Line <17> name print
Line <17> nil
Line <17> mod %
Line <17> name a Line <17> name a
Line <17> equal = Line <17> nil nil
Line <17> equal =
Line <17> name b
Line <17> parac )
Line <17> cbracketo {
Line <17> newline Line <17> newline
Line <17> newline Line <17> newline
Line <18> name print Line <18> cbracketc }
Line <18> parao (
Line <18> string Doing a test!
Line <18> parac )
Line <18> newline Line <18> newline
Line <18> newline Line <18> newline
Line <19> name if Line <19> name while
Line <19> parao ( Line <19> parao (
Line <19> name a Line <19> true true
Line <19> not !
Line <19> equal =
Line <19> name b
Line <19> parac ) Line <19> parac )
Line <19> cbracketo { Line <19> cbracketo {
Line <19> newline Line <19> newline
Line <19> newline Line <19> newline
Line <20> name print Line <20> name a
Line <20> parao ( Line <20> equal =
Line <20> string Doing more tests! Line <20> name a
Line <20> parac ) Line <20> plus +
Line <20> number 1
Line <20> newline Line <20> newline
Line <20> newline Line <20> newline
Line <21> cbracketc } Line <21> name print
Line <21> parao (
Line <21> name a
Line <21> parac )
Line <21> newline Line <21> newline
Line <21> newline Line <21> newline
Line <22> cbracketc } Line <22> cbracketc }
Line <22> name elseif
Line <22> parao (
Line <22> name a1
Line <22> equal =
Line <22> equal =
Line <22> number 10
Line <22> parac )
Line <22> cbracketo {
Line <22> newline Line <22> newline
Line <22> newline Line <22> newline
Line <23> name print
Line <23> parao (
Line <23> string Does this work?
Line <23> parac )
Line <23> newline Line <23> newline
Line <23> newline Line <23> newline
Line <24> cbracketc } Line <24> bracketo [
Line <24> name else Line <24> name fact
Line <24> cbracketo { Line <24> colon :
Line <24> name function
Line <24> parao (
Line <24> name n
Line <24> parac )
Line <24> bracketc ]
Line <24> newline Line <24> newline
Line <24> newline Line <24> newline
Line <25> name print Line <25> name if
Line <25> parao ( Line <25> parao (
Line <25> string This is an else! Line <25> name n
Line <25> equal =
Line <25> equal =
Line <25> number 1
Line <25> or
Line <25> name n
Line <25> equal =
Line <25> equal =
Line <25> number 0
Line <25> parac ) Line <25> parac )
Line <25> newline Line <25> newline
Line <25> newline Line <25> newline
Line <26> cbracketc } Line <26> ret
Line <26> number 1
Line <26> newline Line <26> newline
Line <26> newline Line <26> newline
Line <27> name else
Line <27> newline Line <27> newline
Line <27> newline Line <27> newline
Line <28> name if Line <28> ret
Line <28> name n
Line <28> multiply *
Line <28> name fact
Line <28> parao ( Line <28> parao (
Line <28> name a1 Line <28> name n
Line <28> not ! Line <28> minus -
Line <28> equal = Line <28> number 1
Line <28> number 10
Line <28> parac ) Line <28> parac )
Line <28> name this
Line <28> parao (
Line <28> parac )
Line <28> pipe |
Line <28> cbracketo {
Line <28> newline Line <28> newline
Line <28> newline Line <28> newline
Line <29> name print
Line <29> parao (
Line <29> string Do you work?
Line <29> parac )
Line <29> newline Line <29> newline
Line <29> newline Line <29> newline
Line <30> cbracketc } Line <30> bracketo [
Line <30> name this
Line <30> colon :
Line <30> name function
Line <30> parao (
Line <30> parac )
Line <30> bracketc ]
Line <30> newline Line <30> newline
Line <30> newline Line <30> newline
Line <31> name print
Line <31> parao (
Line <31> string This
Line <31> parac )
Line <31> newline Line <31> newline
Line <31> newline Line <31> newline
Line <32> name count
Line <32> equal =
Line <32> number 0
Line <32> newline Line <32> newline
Line <32> newline Line <32> newline
Line <33> name while Line <33> bracketo [
Line <33> name that
Line <33> colon :
Line <33> name function
Line <33> parao ( Line <33> parao (
Line <33> name count
Line <33> anglebracketO <
Line <33> number 10
Line <33> parac ) Line <33> parac )
Line <33> cbracketo { Line <33> bracketc ]
Line <33> newline Line <33> newline
Line <33> newline Line <33> newline
Line <34> name print Line <34> name print
Line <34> parao ( Line <34> parao (
Line <34> string Count: Line <34> string That
Line <34> plus +
Line <34> name count
Line <34> parac ) Line <34> parac )
Line <34> newline Line <34> newline
Line <34> newline Line <34> newline
Line <35> name count
Line <35> equal =
Line <35> name count
Line <35> plus +
Line <35> number 1
Line <35> newline Line <35> newline
Line <35> newline Line <35> newline
Line <36> cbracketc } Line <36> bracketo [
Line <36> name Bob
Line <36> colon :
Line <36> name char
Line <36> bracketc ]
Line <36> newline Line <36> newline
Line <36> newline Line <36> newline
Line <37> newline Line <37> newline
Line <37> newline
Line <38> newline Line <38> newline
Line <38> newline
Line <39> name print
Line <39> parao (
Line <39> string This is coming along nicely!
Line <39> parac )
Line <39> newline
Line <39> newline Line <39> newline
Line <40> name unknown
Line <40> equal =
Line <40> string Some Random Guy
Line <40> newline Line <40> newline
Line <40> newline Line <40> newline
Line <41> name print Line <41> name age
Line <41> parao ( Line <41> equal =
Line <41> string concat test Line <41> number 0.24
Line <41> parac )
Line <41> newline Line <41> newline
Line <41> newline Line <41> newline
Line <42> name test1 Line <42> name money
Line <42> equal = Line <42> equal =
Line <42> string Hello Line <42> number 100
Line <42> newline Line <42> newline
Line <42> newline Line <42> newline
Line <43> name print Line <43> name excited
Line <43> parao ( Line <43> colon :
Line <43> number 2.2 Line <43> string path/to/file
Line <43> plus +
Line <43> name test1
Line <43> plus +
Line <43> string World!
Line <43> plus +
Line <43> name fake
Line <43> parac )
Line <43> newline Line <43> newline
Line <43> newline Line <43> newline
Line <44> newline Line <43> eof
Line <45> newline
Line <46> newline
Line <47> name if
Line <47> parao (
Line <47> name a
Line <47> equal =
Line <47> equal =
Line <47> nil nil
Line <47> parac )
Line <47> name this
Line <47> parao (
Line <47> parac )
Line <47> pipe |
Line <47> name that
Line <47> parao (
Line <47> parac )
Line <47> newline
Line <47> newline
Line <48> newline
Line <48> newline
Line <49> newline
Line <49> newline
Line <50> bracketo [
Line <50> name this
Line <50> colon :
Line <50> name function
Line <50> parao (
Line <50> parac )
Line <50> bracketc ]
Line <50> newline
Line <50> newline
Line <51> name print
Line <51> parao (
Line <51> string This
Line <51> parac )
Line <51> newline
Line <51> newline
Line <52> newline
Line <52> newline
Line <53> bracketo [
Line <53> name that
Line <53> colon :
Line <53> name function
Line <53> parao (
Line <53> parac )
Line <53> bracketc ]
Line <53> newline
Line <53> newline
Line <54> name print
Line <54> parao (
Line <54> string That
Line <54> parac )
Line <54> newline
Line <54> newline
Line <55> newline
Line <55> newline
Line <56> bracketo [
Line <56> name Bob
Line <56> colon :
Line <56> name char
Line <56> bracketc ]
Line <56> newline
Line <56> newline
Line <57> newline
Line <58> newline
Line <59> newline
Line <60> name unknown
Line <60> equal =
Line <60> string Some Random Guy
Line <60> newline
Line <60> newline
Line <61> name age
Line <61> equal =
Line <61> number .24
Line <61> newline
Line <61> newline
Line <62> name money
Line <62> equal =
Line <62> number 100
Line <62> newline
Line <62> newline
Line <63> name excited
Line <63> colon :
Line <63> string path/to/file
Line <63> newline
Line <63> newline
Line <64> newline
Line <64> newline
Line <65> bracketo [
Line <65> name test1
Line <65> colon :
Line <65> name function
Line <65> parao (
Line <65> parac )
Line <65> bracketc ]
Line <65> newline
Line <65> newline
Line <66> string Inside a function!
Line <66> newline
Line <66> newline
Line <67> newline
Line <68> newline
Line <69> newline
Line <69> newline
Line <70> bracketo [
Line <70> name newblock
Line <70> colon :
Line <70> name function
Line <70> parao (
Line <70> name a
Line <70> seperator ,
Line <70> name b
Line <70> seperator ,
Line <70> name c
Line <70> parac )
Line <70> bracketc ]
Line <70> newline
Line <70> newline
Line <71> string Func Arguments: a = `a`, b = `b`, c = `c`
Line <71> newline
Line <71> newline
Line <72> string Time to return
Line <72> newline
Line <72> newline
Line <73> ret
Line <73> name a
Line <73> plus +
Line <73> name b
Line <73> plus +
Line <73> name c
Line <73> newline
Line <73> newline
Line <73> eof
Line <1> newline
Line <1> newline
Line <1> bracketo [
Line <1> name default
Line <1> colon :
Line <1> name char
Line <1> bracketc ]
Line <1> newline
Line <1> newline
Line <2> newline
Line <3> name money
Line <3> equal =
Line <3> number 0
Line <3> newline
Line <3> newline
Line <4> name test
Line <4> equal =
Line <4> nil nil
Line <4> newline
Line <4> newline
Line <5> newline
Line <5> newline
Line <6> bracketo [
Line <6> name Ryan
Line <6> colon :
Line <6> name char
Line <6> bracketc ]
Line <6> newline
Line <6> newline
Line <7> name age
Line <7> equal =
Line <7> number 21
Line <7> newline
Line <7> newline
Line <8> name money
Line <8> equal =
Line <8> number 1000
Line <8> newline
Line <8> newline
Line <9> name lname
Line <9> equal =
Line <9> string Ward
Line <9> newline
Line <9> newline
Line <10> name known
Line <10> equal =
Line <10> true true
Line <10> newline
Line <10> newline
Line <11> newline
Line <12> name calm
Line <12> colon :
Line <12> string ./path/to/file
Line <12> newline
Line <12> newline
Line <13> name excited
Line <13> colon :
Line <13> string ./path/to/file
Line <13> newline
Line <13> newline
Line <14> newline
Line <14> newline
Line <15> bracketo [
Line <15> name step
Line <15> colon :
Line <15> name function
Line <15> parao (
Line <15> name a
Line <15> seperator ,
Line <15> name b
Line <15> seperator ,
Line <15> name c
Line <15> parac )
Line <15> bracketc ]
Line <15> newline
Line <15> newline
Line <16> string Testing...
Line <16> newline
Line <17> newline
Line <18> name e
Line <18> equal =
Line <18> string somestring
Line <18> newline
Line <18> newline
Line <19> name e
Line <19> equal =
Line <19> nil nil
Line <19> newline
Line <19> newline
Line <20> name g
Line <20> equal =
Line <20> false false
Line <20> newline
Line <20> newline
Line <21> ret
Line <21> name d
Line <21> newline
Line <21> newline
Line <22> newline
Line <22> newline
Line <23> bracketo [
Line <23> name inv
Line <23> colon :
Line <23> name env
Line <23> bracketc ]
Line <23> newline
Line <23> newline
Line <24> name slot1
Line <24> equal =
Line <24> string S1
Line <24> newline
Line <24> newline
Line <25> name slot2
Line <25> equal =
Line <25> string S2
Line <25> newline
Line <25> newline
Line <26> name slot3
Line <26> equal =
Line <26> string S3
Line <26> newline
Line <26> newline
Line <27> name slot4
Line <27> equal =
Line <27> string S4
Line <27> newline
Line <27> newline
Line <28> name slot5
Line <28> equal =
Line <28> string S5
Line <28> newline
Line <28> newline
Line <29> name slot6
Line <29> equal =
Line <29> string S6
Line <29> newline
Line <29> newline
Line <30> name slot7
Line <30> equal =
Line <30> string S7
Line <30> newline
Line <30> newline
Line <31> name slot8
Line <31> equal =
Line <31> string S8
Line <31> newline
Line <31> newline
Line <31> eof

View File

@ -6,47 +6,22 @@ enable forwardlabels // Do most of your labels exist ahead?
enable savestate enable savestate
//enable leaking //enable leaking
//enable debugging //enable debugging
loadfile "loadtest.dms" //loadfile "loadtest.dms"
version 0.2 version 0.2
using extendedDefine using extendedDefine
[main] [main]
a1 = 10 a=0
b1 = 15 while(true)
print("this" + " or " + "that") asm {
add %a %a 1
if(a==b){ func %print nil %a nil
print("Doing a test!")
if(a!=b){
print("Doing more tests!")
}
} elseif (a1==10) {
print("Does this work?")
} else {
print("This is an else!")
} }
if (a1!=10)this() | { [fact:function(n)]
print("Do you work?") if(n==1 or n==0)
} return 1
else
count = 0 return n * fact(n-1)
while(count<10){
print("Count: " + count)
count = count + 1
}
// for(x, 10, 1, -1){
// print(x)
// }
print("This is coming along nicely!")
print("concat test")
test1 = "Hello "
print(2.2+test1+"World!"+fake)
if(a==nil) this()|that()
[this:function()] [this:function()]
print("This") print("This")
@ -62,13 +37,3 @@ using extendedDefine
age = .24 age = .24
money = 100 money = 100
excited: "path/to/file" excited: "path/to/file"
[test1:function()]
"Inside a function!"
//val = newblock(1,2,3)
//"val = `val`"
[newblock:function(a,b,c)]
"Func Arguments: a = `a`, b = `b`, c = `c`"
"Time to return"
return a+b+c

View File

@ -1,5 +1,5 @@
# DMS # DMS
The Dialogue Management Script's goal is to provide a nice and simple way to have dialogue for games. The Dialogue Management Script's goal is to provide a nice and simple way to have dialogue for games, while also providing a fully functioning language to perform login in.
# Todo # Todo
- [X] ~~Implement bytecode for if/else if/else statements~~ - [X] ~~Implement bytecode for if/else if/else statements~~