diff --git a/DMS/LineParser.h b/DMS/LineParser.h index 38f929d..423bba5 100644 --- a/DMS/LineParser.h +++ b/DMS/LineParser.h @@ -33,6 +33,7 @@ namespace dms { tokens::token peek(); tokens::token last(); std::vector 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 = 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); @@ -64,7 +65,7 @@ namespace dms { dms_state* state = nullptr; void doCheck(passer* stream, std::vector* t_vec, size_t line, bool& isNum, bool& hasDec, std::vector* buffer); void _Parse(tokenstream* stream); - void ParseLoop(tokenstream* stream); + bool ParseLoop(tokenstream* stream, size_t count=0); std::stack lastCall; // Match Process Code bool match_process_debug(tokenstream* stream); @@ -88,6 +89,9 @@ namespace dms { bool match_process_andor(tokenstream* stream,value& v); bool match_process_scope(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 void buildGoto(std::string g, bool v = false); @@ -96,10 +100,12 @@ namespace dms { void buildLabel(std::string l); void buildSpeed(double s); void buildWait(double w); + void buildCmd(codes::op,std::vector); // Utils std::string random_string(std::size_t length); + bool manageCount(bool cond, size_t c,size_t&); bool notBalanced(std::vector ts, size_t last_line, tokenstream* stream, std::string o, std::string c); void badSymbol(errors::errortype err, tokenstream* stream); void badSymbol(tokenstream* stream); diff --git a/DMS/LineParserBuilds.cpp b/DMS/LineParserBuilds.cpp index 33a2882..a6db31f 100644 --- a/DMS/LineParserBuilds.cpp +++ b/DMS/LineParserBuilds.cpp @@ -48,4 +48,11 @@ namespace dms { c->args.push(value(w)); current_chunk->addCmd(c); } + void LineParser::buildCmd(codes::op op, std::vector args) + { + cmd* c = new cmd; + c->opcode = op; + c->args.args = args; + current_chunk->addCmd(c); + } } \ No newline at end of file diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index d42a698..96c9bae 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -5,7 +5,7 @@ using namespace dms::utils; namespace dms { bool LineParser::match_process_standard(tokenstream* stream, value& v) { stream->chomp(newline); - //utils::debug(stream->peek()); + utils::debug(stream->peek()); if (stream->peek().type == tokens::none) { return false; } @@ -73,10 +73,6 @@ namespace dms { } return true; } - if (match_process_andor(stream, v)) { - match_process_condition(stream, v); - return true; - } if (match_process_expression(stream, v)) { match_process_condition(stream,v); return true; @@ -105,8 +101,7 @@ namespace dms { match_process_condition(stream, v); return true; } - else if (stream->match(tokens::number)) { - v.set(std::stod(stream->next().name)); + else if (match_process_number(stream, v)) { match_process_condition(stream, v); return true; } @@ -139,6 +134,9 @@ namespace dms { else if (stream->match(tokens::newline)) { stream->next(); return match_process_standard(stream,v); + } else if (match_process_andor(stream, v)) { + match_process_condition(stream, v); + return true; } return false; } @@ -212,7 +210,7 @@ namespace dms { stream->next(); } else { - return match_process_andor(stream,v); + return false; } // So if all is good we continue here value right = value(datatypes::variable); @@ -459,7 +457,7 @@ namespace dms { } bool LineParser::match_process_return(tokenstream* stream) { // 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)) { cmd* c = new cmd; c->opcode = codes::RETN; @@ -937,6 +935,9 @@ namespace dms { ParseLoop(&tempstream); // Done return true; } + else if (ParseLoop(stream, 1)) { + return true; // Let's try and match one command + } return false; } bool LineParser::match_process_while(tokenstream* stream) @@ -948,28 +949,311 @@ namespace dms { std::string wstart = std::string("WHS_") + random_string(4); std::string wend = std::string("WHE_") + random_string(4); 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 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; + c->opcode = codes::IFFF; + c->args.push(ref); + c->args.push(value(wend)); + current_chunk->addCmd(c); + if (match_process_scope(stream)) { + buildGoto(wstart); + buildLabel(wend); + return true; + } + else { + badSymbol(stream); + } + } + else { + badSymbol(stream); + 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 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; - c->opcode = codes::IFFF; - c->args.push(ref); - c->args.push(value(wend)); - current_chunk->addCmd(c); + int count = 0; + value iter; + value start; + value end; + value inc = value(1); + if (tempstream.match(tokens::name,tokens::equal)) { + std::vector 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)) { - buildGoto(wstart); - buildLabel(wend); + buildCmd(codes::ADD, {iter,inc,iter}); + buildGoto(fstart); + buildLabel(fend); return true; } else { badSymbol(stream); } } - else { - badSymbol(stream); - return false; + } + 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 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 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) { /*if(this) { * then() @@ -997,32 +1281,38 @@ namespace dms { if (match_process_standard(&tmpstream,cmp)) { std::string ifend = std::string("IFE_") + random_string(4); std::string next = std::string("IFF_") + random_string(4); - if (stream->match(tokens::cbracketo)) { - size_t last_line = stream->last().line_num; + cmd* c = new cmd; + 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 toks = stream->next(tokens::cbracketo, tokens::cbracketc); if (notBalanced(toks, last_line, stream, "{", "}")) return false; toks.pop_back(); tokenstream tempstream(&toks); - cmd* c = new cmd; - c->opcode = codes::IFFF; - c->args.push(cmp); - c->args.push(value(next)); - current_chunk->addCmd(c); - ParseLoop(&tempstream); + ParseLoop(&tempstream);*/ buildGoto(ifend); 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); // We keep trying to match else if/else until nothing is left return true; } 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)) { stream->chomp(newline); if (stream->match(tokens::pipe)) { @@ -1057,16 +1347,11 @@ namespace dms { return false; // TODO finish this } 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(); - size_t last_line = stream->last().line_num; - std::vector 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; + if (match_process_scope(stream)) { + return true; + } } return false; } @@ -1083,22 +1368,31 @@ namespace dms { //buildLabel(iff); if (match_process_standard(&tmpstream, cmp)) { std::string next = std::string("IFF_") + random_string(4); - if (stream->match(tokens::cbracketo)) { - size_t last_line = stream->last().line_num; + if (match_process_scope(stream)) { + /*size_t last_line = stream->last().line_num; std::vector toks = stream->next(tokens::cbracketo, tokens::cbracketc); if (notBalanced(ts, last_line, stream, "{", "}")) return false; toks.pop_back(); - tokenstream tempstream(&toks); + tokenstream tempstream(&toks);*/ cmd* c = new cmd; c->opcode = codes::IFFF; c->args.push(cmp); c->args.push(value(next)); current_chunk->addCmd(c); - ParseLoop(&tempstream); + //ParseLoop(&tempstream); buildGoto(ifend); buildLabel(next); + 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; + } + } // We keep trying to match else if/else until nothing is left return true; } @@ -1134,13 +1428,13 @@ namespace dms { stream->store(current_chunk); cmd* lastcmd = nullptr; // 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 cmd* c = new cmd; value wv; - value left; // lefthand + value left; // left hand codes::op op; // opperator - value right; // righthand + value right; // right hand reset(left, op, right); size_t loops = 0; bool hasOP = false; diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index 3bdb7f6..0cee25e 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -342,13 +342,14 @@ namespace dms { outputFile.close(); } } - void LineParser::ParseLoop(tokenstream* stream) { - if (stop) return; - token current = stream->next(); + bool LineParser::ParseLoop(tokenstream* stream, size_t count) { + if (stop) return false; + size_t current_count=0; + token current = token{tokentype::newline,codes::NOOP}; cmd* flagcmd = new cmd; value nil; while (stream->peek().type != tokens::none) { - if (stop) return; + if (stop) return false; debugInvoker(stream); //utils::debug(current); //utils::print("[flags]"); @@ -372,7 +373,7 @@ namespace dms { else if (code == codes::ENTR && tok == tokens::name) { 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 }); - return; + return false; } state->entry = temp[0].name; flagcmd->opcode = code; @@ -408,20 +409,18 @@ namespace dms { } else { state->push_error(errors::error{ errors::badtoken,concat("Expected got: ", current, temp[0]),true,line,current_chunk }); - return; + return false; } } // Default block - if (stream->match(tokens::newline, tokens::bracketo, tokens::name, tokens::bracketc, tokens::newline)) { - stream->next(); + if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc, tokens::newline)) { stream->next(); std::string name = stream->next().name; createBlock(name, bt_block); line = stream->next().line_num; // Consume } // 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)) { - stream->next(); + else if (stream->match(tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::bracketc)) { stream->next(); std::string name = stream->next().name; line = stream->next().line_num; @@ -441,10 +440,9 @@ namespace dms { stream->next(); } // 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; stream->next(); - stream->next(); 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 std::string b = stream->next().name; @@ -470,58 +468,69 @@ namespace dms { str << "Unexpected symbol: " << tokens[i]; 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 current_chunk->params = args; // Thats should be all we need to do - stream->next(); + 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(); + } } else { str << "'function' keyword expected got " << b; state->push_error(errors::error{ errors::badtoken, str.str(),true,line,current_chunk }); - return; + return false; } } // Control Handle all controls here - match_process_while(stream); - match_process_IFFF(stream); + manageCount(match_process_while(stream),count,current_count); + manageCount(match_process_for(stream), count, current_count); + manageCount(match_process_IFFF(stream), count, current_count); // Let's handle function stuff! //utils::print("[return]"); - match_process_return(stream); + manageCount(match_process_return(stream), count, current_count); //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]"); 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); } //utils::print("[func]"); - match_process_function(stream, nil); // Naked Function + manageCount(match_process_function(stream, nil), count, current_count); // Naked Function //utils::print("[assn]"); - match_process_assignment(stream); + manageCount(match_process_assignment(stream), count, current_count); //utils::print("[debug]"); - match_process_debug(stream); + manageCount(match_process_debug(stream), count, current_count); //utils::print("[goto]"); - match_process_goto(stream); + manageCount(match_process_goto(stream), count, current_count); //utils::print("[exit]"); - match_process_exit(stream); + manageCount(match_process_exit(stream), count, current_count); //utils::print("[wait]"); - match_process_wait(stream); + manageCount(match_process_wait(stream), count, current_count); //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)) current = stream->next(); - //utils::debug(stream->peek()); + utils::debug(stream->peek()); } } void LineParser::_Parse(tokenstream* stream) { if (stop) return; - createBlock("$INIT", blocktype::bt_block); + createBlock("$INIT", bt_block); ParseLoop(stream); 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! } } \ No newline at end of file diff --git a/DMS/LineParserUtils.cpp b/DMS/LineParserUtils.cpp index f23322d..874d363 100644 --- a/DMS/LineParserUtils.cpp +++ b/DMS/LineParserUtils.cpp @@ -94,6 +94,10 @@ namespace dms { temp.push_back(next()); return temp; } + bool tokenstream::can() + { + return peek().type != tokens::none; + } uint8_t passer::next() { if (stream.size() == pos) { return NULL; @@ -141,6 +145,14 @@ namespace dms { 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 ts, size_t last_line, tokenstream* stream, std::string o, std::string c) { if (ts.size() == 0) { stop = true; diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index e30492c..6ddc9b8 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -7,14 +7,14 @@ namespace dms { init_init = true; cmd* c = new cmd; 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->args.push(value(key, datatypes::variable)); c->args.push(value(key, datatypes::block)); chunks["$INIT"]->addCmd(c); c = new cmd; } - else if (val->type == blocktype::bt_method) { + else if (val->type == bt_method) { c->opcode = codes::RETN; c->args.push(value()); val->addCmd(c); @@ -95,13 +95,13 @@ namespace dms { return true; } 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) { - 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) { - 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) { return (chunks.count(bk_name)); diff --git a/DMS/dump.bin b/DMS/dump.bin index 8601de8..e1bedce 100644 Binary files a/DMS/dump.bin and b/DMS/dump.bin differ diff --git a/DMS/dump.txt b/DMS/dump.txt index b539176..3588104 100644 --- a/DMS/dump.txt +++ b/DMS/dump.txt @@ -22,9 +22,6 @@ Line <6> newline Line <6> newline Line <7> newline Line <8> newline -Line <9> flag -Line <9> string loadtest.dms -Line <9> newline Line <9> newline Line <10> flag Line <10> number 0.2 @@ -39,467 +36,172 @@ Line <12> name main Line <12> bracketc ] Line <12> newline Line <12> newline -Line <13> name a1 +Line <13> name a Line <13> equal = -Line <13> number 10 +Line <13> number 0 Line <13> newline Line <13> newline -Line <14> name b1 -Line <14> equal = -Line <14> number 15 +Line <14> name while +Line <14> parao ( +Line <14> true true +Line <14> parac ) Line <14> newline Line <14> newline -Line <15> name print -Line <15> parao ( -Line <15> string this -Line <15> plus + -Line <15> string or -Line <15> plus + -Line <15> string that -Line <15> parac ) +Line <15> name asm +Line <15> cbracketo { 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 <17> name if -Line <17> parao ( +Line <17> name func +Line <17> mod % +Line <17> name print +Line <17> nil +Line <17> mod % Line <17> name a -Line <17> equal = -Line <17> equal = -Line <17> name b -Line <17> parac ) -Line <17> cbracketo { +Line <17> nil nil Line <17> newline Line <17> newline -Line <18> name print -Line <18> parao ( -Line <18> string Doing a test! -Line <18> parac ) +Line <18> cbracketc } Line <18> newline Line <18> newline -Line <19> name if +Line <19> name while Line <19> parao ( -Line <19> name a -Line <19> not ! -Line <19> equal = -Line <19> name b +Line <19> true true Line <19> parac ) Line <19> cbracketo { Line <19> newline Line <19> newline -Line <20> name print -Line <20> parao ( -Line <20> string Doing more tests! -Line <20> parac ) +Line <20> name a +Line <20> equal = +Line <20> name a +Line <20> plus + +Line <20> number 1 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 <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 <23> name print -Line <23> parao ( -Line <23> string Does this work? -Line <23> parac ) Line <23> newline Line <23> newline -Line <24> cbracketc } -Line <24> name else -Line <24> cbracketo { +Line <24> bracketo [ +Line <24> name fact +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 <25> name print +Line <25> name if 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> newline Line <25> newline -Line <26> cbracketc } +Line <26> ret +Line <26> number 1 Line <26> newline Line <26> newline +Line <27> name else 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> name a1 -Line <28> not ! -Line <28> equal = -Line <28> number 10 +Line <28> name n +Line <28> minus - +Line <28> number 1 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 <29> name print -Line <29> parao ( -Line <29> string Do you work? -Line <29> parac ) 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 <31> name print +Line <31> parao ( +Line <31> string This +Line <31> parac ) Line <31> newline Line <31> newline -Line <32> name count -Line <32> equal = -Line <32> number 0 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> name count -Line <33> anglebracketO < -Line <33> number 10 Line <33> parac ) -Line <33> cbracketo { +Line <33> bracketc ] Line <33> newline Line <33> newline Line <34> name print Line <34> parao ( -Line <34> string Count: -Line <34> plus + -Line <34> name count +Line <34> string That Line <34> parac ) 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 <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 <37> newline -Line <37> 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 <40> name unknown +Line <40> equal = +Line <40> string Some Random Guy Line <40> newline Line <40> newline -Line <41> name print -Line <41> parao ( -Line <41> string concat test -Line <41> parac ) +Line <41> name age +Line <41> equal = +Line <41> number 0.24 Line <41> newline Line <41> newline -Line <42> name test1 +Line <42> name money Line <42> equal = -Line <42> string Hello +Line <42> number 100 Line <42> newline Line <42> newline -Line <43> name print -Line <43> parao ( -Line <43> number 2.2 -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> name excited +Line <43> colon : +Line <43> string path/to/file Line <43> newline Line <43> newline -Line <44> newline -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 +Line <43> eof diff --git a/DMS/test.dms b/DMS/test.dms index 8e812df..df8a568 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -6,47 +6,22 @@ enable forwardlabels // Do most of your labels exist ahead? enable savestate //enable leaking //enable debugging -loadfile "loadtest.dms" +//loadfile "loadtest.dms" version 0.2 using extendedDefine [main] - a1 = 10 - b1 = 15 - print("this" + " or " + "that") - - if(a==b){ - print("Doing a test!") - if(a!=b){ - print("Doing more tests!") + a=0 + while(true) + asm { + add %a %a 1 + func %print nil %a nil } - } elseif (a1==10) { - print("Does this work?") - } else { - print("This is an else!") - } - - if (a1!=10)this() | { - print("Do you work?") - } - - count = 0 - 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() - + +[fact:function(n)] + if(n==1 or n==0) + return 1 + else + return n * fact(n-1) [this:function()] print("This") @@ -62,13 +37,3 @@ using extendedDefine age = .24 money = 100 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 diff --git a/README.md b/README.md index 448c6ac..869730c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # 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 - [X] ~~Implement bytecode for if/else if/else statements~~