diff --git a/DMS/LineParser.h b/DMS/LineParser.h index c98664a..38f929d 100644 --- a/DMS/LineParser.h +++ b/DMS/LineParser.h @@ -27,6 +27,7 @@ namespace dms { void init(std::vector* ptr); tokens::token next(); void prev(); + void chomp(tokens::tokentype t); std::vector next(tokens::tokentype to, tokens::tokentype tc); std::vector next(tokens::tokentype to, tokens::tokentype tc, bool nonewline); tokens::token peek(); @@ -86,6 +87,7 @@ namespace dms { bool match_process_condition(tokenstream* stream, value& v); bool match_process_andor(tokenstream* stream,value& v); bool match_process_scope(tokenstream* stream); + bool match_process_while(tokenstream* stream); // Build void buildGoto(std::string g, bool v = false); diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index bc5e660..d42a698 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -4,6 +4,7 @@ using namespace dms::utils; // TODO: process if elseif else statements, for loops and while loops namespace dms { bool LineParser::match_process_standard(tokenstream* stream, value& v) { + stream->chomp(newline); //utils::debug(stream->peek()); if (stream->peek().type == tokens::none) { return false; @@ -699,7 +700,7 @@ namespace dms { token end = t.back(); t.pop_back(); t.push_back(token{ tokens::seperator,codes::NOOP,"",t[0].line_num }); - t.push_back(token{ tokens::nil,codes::NOOP,"",t[0].line_num }); + t.push_back(token{ tokens::escape,codes::NOOP,"",t[0].line_num }); t.push_back(end); tempstream.init(&t); // Turn tokens we consumed into a tokenstream if (tokn.type==tokens::gotoo) { @@ -739,11 +740,16 @@ namespace dms { // This part we add values to the opcodes for the bytecode FUNC val a1 a2 a3 ... an while (tempstream.peek().type != tokens::none) { // End of stream debugInvoker(stream); + //utils::debug(stream->peek()); tempval = value(datatypes::variable); if (tempstream.match(tokens::seperator)) { // We have a seperator for function arguments tempstream.next(); // Consume it } + else if (tempstream.match(tokens::escape)) { + c->args.push(value(datatypes::escape)); + tempstream.next(); + } else if (match_process_standard(&tempstream, tempval)) { c->args.push(tempval); } @@ -756,8 +762,9 @@ namespace dms { return true; } else { - utils::debug(tempstream.peek()); + //utils::debug(tempstream.peek()); badSymbol(&tempstream); + return false; } } @@ -922,6 +929,7 @@ namespace dms { if (stream->match(cbracketo)) { size_t last_line = stream->last().line_num; std::vector t = stream->next(cbracketo, cbracketc); // Consume and get tokens + t.pop_back(); tokenstream tempstream(&t); if (notBalanced(t, last_line, stream, "{", "}")) return false; @@ -931,6 +939,37 @@ namespace dms { } return false; } + bool LineParser::match_process_while(tokenstream* stream) + { + if (stream->match(tokens::name) && stream->peek().name == "while") { + stream->next(); + stream->chomp(tokens::newline); + value ref(datatypes::variable); + 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)) { + 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_IFFF(tokenstream* stream) { /*if(this) { * then() @@ -954,6 +993,7 @@ namespace dms { tokenstream tmpstream(&ts); value cmp(datatypes::variable); value nil; + stream->chomp(newline); if (match_process_standard(&tmpstream,cmp)) { std::string ifend = std::string("IFE_") + random_string(4); std::string next = std::string("IFF_") + random_string(4); @@ -984,8 +1024,10 @@ namespace dms { c->args.push(value(next)); current_chunk->addCmd(c); if (match_process_function(stream, nil)) { + stream->chomp(newline); if (stream->match(tokens::pipe)) { stream->next(); + stream->chomp(newline); buildGoto(ifend); buildLabel(next); if (!match_process_function(stream, nil) && !match_process_scope(stream)) { @@ -1092,7 +1134,7 @@ 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::name) || stream->match(tokens::parao)) && stream->tokens.size()>=3) { + if ((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; diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index f279cc5..3bdb7f6 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -352,7 +352,8 @@ namespace dms { debugInvoker(stream); //utils::debug(current); //utils::print("[flags]"); - if (current.type == tokens::flag) { + if (stream->match(flag)) { + current = stream->next(); temp = stream->next(tokens::newline); stream->prev(); // Unconsume the newline piece if (temp.size() != 2) { @@ -437,6 +438,7 @@ namespace dms { else if (temp == "menu") { createBlock(name, bt_menu); } + stream->next(); } // Function block type else if (stream->match(tokens::newline, tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::parao)) { @@ -474,6 +476,7 @@ namespace dms { // 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(); } else { str << "'function' keyword expected got " << b; @@ -483,6 +486,7 @@ namespace dms { } } // Control Handle all controls here + match_process_while(stream); match_process_IFFF(stream); // Let's handle function stuff! //utils::print("[return]"); @@ -508,7 +512,9 @@ namespace dms { match_process_wait(stream); //utils::print("[jump]"); match_process_jump(stream); - current = stream->next(); + if(stream->match(newline) || stream->match(eof)) + current = stream->next(); + //utils::debug(stream->peek()); } } void LineParser::_Parse(tokenstream* stream) { diff --git a/DMS/LineParserUtils.cpp b/DMS/LineParserUtils.cpp index c7670cc..f23322d 100644 --- a/DMS/LineParserUtils.cpp +++ b/DMS/LineParserUtils.cpp @@ -17,6 +17,11 @@ namespace dms { void tokenstream::prev() { pos--; } + void tokenstream::chomp(tokens::tokentype t) + { + while (peek().type == t) + next(); + } void tokenstream::store(chunk* c) { stack.push(c->cmds.size()); spos.push(pos); @@ -297,6 +302,11 @@ namespace dms { chunk_type = bk_type; current_chunk->type = bk_type; + cmd* bn = new cmd; + bn->opcode = codes::BLCK; + bn->args.push(value(bk_name)); + bn->args.push(value(bk_type)); + current_chunk->addCmd(bn); if (state->isEnabled("debugging")) { cmd* c = new cmd; c->opcode = codes::FILE; diff --git a/DMS/chunk.h b/DMS/chunk.h index 6b067be..6a5bf07 100644 --- a/DMS/chunk.h +++ b/DMS/chunk.h @@ -26,7 +26,7 @@ namespace dms { void addLabel(std::string name); friend std::ostream& operator << (std::ostream& out, const chunk& c) { for (size_t i = 0; i < c.cmds.size(); i++) { - out << *(c.cmds[i]) << std::endl; + out << *(c.cmds[i]) << std::endl;// (char)255 << (char)254; } return out; } diff --git a/DMS/codes.cpp b/DMS/codes.cpp index 05a045d..57ce06d 100644 --- a/DMS/codes.cpp +++ b/DMS/codes.cpp @@ -13,7 +13,7 @@ const std::string dms::codes::list[] = { "ASGN", "LABL", "CHOI", - "OPTN", + "BLCK", "FORE", "WHLE", "FUNC", diff --git a/DMS/codes.h b/DMS/codes.h index 38f2216..b4ef9c4 100644 --- a/DMS/codes.h +++ b/DMS/codes.h @@ -10,12 +10,12 @@ namespace dms::codes { LOAD, // Done VERN, // Done USIN, // TODO - STAT, // Done + STAT, DISP, // Done ASGN, // Done LABL, // Done CHOI, // Done - OPTN, + BLCK, FORE, WHLE, FUNC, // Done diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index 0272a8c..e30492c 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -73,7 +73,12 @@ namespace dms { enable("statesave"); chunk* c = new chunk; c->name = "$END"; - c->type = blocktype::bt_block; + c->type = bt_block; + cmd* bn = new cmd; + bn->opcode = codes::BLCK; + bn->args.push(value("$END")); + bn->args.push(value(bt_block)); + c->addCmd(bn); cmd* cc = new cmd; cc->opcode = codes::EXIT; cc->args.push(value(0)); @@ -113,19 +118,6 @@ namespace dms { } return false; } - void dms_state::dump(errors::error err) { - std::cout << std::endl << "STATE DUMP" << std::endl << "Number of chunks: " << chunks.size(); - std::ofstream outputFile("dump.bin"); - for (const auto& [key, val] : chunks) { - std::cout << "Key: " << key << "<" << getBlockType(val->type) << ">" << std::endl << *val << std::endl; - outputFile << "Key: " << key << "<" << getBlockType(val->type) << ">" << std::endl << *val << std::endl; - } - //If the error has a chunk then we get the data from it - if (err.current_chunk != nullptr) { - outputFile << err.current_chunk->name << ":" << std::endl << *err.current_chunk << std::endl; - } - outputFile.close(); - } bool dms_state::hasError() { return stop; } @@ -138,14 +130,10 @@ namespace dms { (*getMem())[var.getPrintable()] = val; return true; } - void dms_state::dump(bool print) { - if (print) - std::cout << "Number of chunks: " << chunks.size() << std::endl; - std::ofstream outputFile("dump.bin"); + void dms_state::dump(std::string fn) { + std::ofstream outputFile(fn); for (const auto& [key, val] : chunks) { - if(print) - std::cout << "Key: " << key << "<" << getBlockType(val->type) << ">" << std::endl << *val << std::endl; - outputFile << "Key: " << key << "<" << getBlockType(val->type) << ">" << std::endl << *val << std::endl; + outputFile << *val << std::endl; } outputFile.close(); } @@ -157,7 +145,7 @@ namespace dms { std::cout << err.err_msg << " On Line <" << err.linenum << ">" << std::endl; } else if (isEnabled("debugging")) { - std::cout << err.err_msg << " In File " << cur_file << " On Line <" << cur_line << ">" << std::endl; + std::cout << err.err_msg << " In file: '" << cur_file << "' on Line <" << cur_line << ">" << std::endl; } else { std::cout << err.err_msg << std::endl; diff --git a/DMS/dms_state.h b/DMS/dms_state.h index 7053cf5..de48ad3 100644 --- a/DMS/dms_state.h +++ b/DMS/dms_state.h @@ -40,8 +40,7 @@ namespace dms { errors::error err; dms_state(); - void dump(errors::error err); - void dump(bool print=false); + void dump(std::string fn = "dump.bin"); void push_error(errors::error err); void push_warning(errors::error err); void push_chunk(std::string s, chunk* c); diff --git a/DMS/dms_state_interpret.cpp b/DMS/dms_state_interpret.cpp index 9e9abc1..b6e865d 100644 --- a/DMS/dms_state_interpret.cpp +++ b/DMS/dms_state_interpret.cpp @@ -438,18 +438,22 @@ namespace dms { break; } case comp::gt: { + if (left.isNil() || right.isNil()) {push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" });return false;} assign(assn, value(left > right)); break; } case comp::gteq: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } assign(assn, value(left >= right)); break; } case comp::lt: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } assign(assn, value(left < right)); break; } case comp::lteq: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } assign(assn, value(left <= right)); break; } diff --git a/DMS/dump.bin b/DMS/dump.bin index 95bdf1c..8601de8 100644 Binary files a/DMS/dump.bin and b/DMS/dump.bin differ diff --git a/DMS/dump.txt b/DMS/dump.txt index 4987894..b539176 100644 --- a/DMS/dump.txt +++ b/DMS/dump.txt @@ -21,9 +21,6 @@ Line <6> name savestate Line <6> newline Line <6> newline Line <7> newline -Line <8> flag -Line <8> name debugging -Line <8> newline Line <8> newline Line <9> flag Line <9> string loadtest.dms @@ -54,12 +51,11 @@ Line <14> newline Line <14> newline Line <15> name print Line <15> parao ( -Line <15> parao ( -Line <15> name a1 -Line <15> not ! -Line <15> equal = -Line <15> name b1 -Line <15> parac ) +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 @@ -158,173 +154,207 @@ Line <30> newline Line <30> 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 <33> name print +Line <33> name while Line <33> parao ( -Line <33> string This is coming along nicely! +Line <33> name count +Line <33> anglebracketO < +Line <33> number 10 Line <33> parac ) +Line <33> cbracketo { 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> parac ) Line <34> newline Line <34> newline -Line <35> name print -Line <35> parao ( -Line <35> string concat test -Line <35> parac ) +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> name test1 -Line <36> equal = -Line <36> string Hello +Line <36> cbracketc } Line <36> newline Line <36> newline -Line <37> name print -Line <37> parao ( -Line <37> number 2.2 -Line <37> plus + -Line <37> name test1 -Line <37> plus + -Line <37> string World! -Line <37> plus + -Line <37> name fake -Line <37> parac ) 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> newline +Line <40> newline +Line <41> name print +Line <41> parao ( +Line <41> string concat test +Line <41> parac ) Line <41> newline Line <41> newline -Line <42> name if -Line <42> parao ( -Line <42> name this +Line <42> name test1 Line <42> equal = -Line <42> equal = -Line <42> name that -Line <42> parac ) -Line <42> name this -Line <42> parao ( -Line <42> parac ) -Line <42> pipe | -Line <42> name that -Line <42> parao ( -Line <42> parac ) +Line <42> string Hello 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> newline Line <43> newline -Line <44> bracketo [ -Line <44> name this -Line <44> colon : -Line <44> name function -Line <44> parao ( -Line <44> parac ) -Line <44> bracketc ] Line <44> newline -Line <44> newline -Line <45> name print -Line <45> parao ( -Line <45> string This -Line <45> parac ) -Line <45> newline Line <45> newline Line <46> newline -Line <46> newline -Line <47> bracketo [ -Line <47> name that -Line <47> colon : -Line <47> name function +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> bracketc ] Line <47> newline Line <47> newline -Line <48> name print -Line <48> parao ( -Line <48> string That -Line <48> parac ) Line <48> newline Line <48> newline Line <49> newline Line <49> newline Line <50> bracketo [ -Line <50> name Bob +Line <50> name this Line <50> colon : -Line <50> name char +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 <54> name unknown -Line <54> equal = -Line <54> string Some Random Guy +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> name age -Line <55> equal = -Line <55> number .24 Line <55> newline Line <55> newline -Line <56> name money -Line <56> equal = -Line <56> number 100 +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> name excited -Line <57> colon : -Line <57> string path/to/file -Line <57> newline Line <57> newline Line <58> newline -Line <58> newline -Line <59> bracketo [ -Line <59> name test1 -Line <59> colon : -Line <59> name function -Line <59> parao ( -Line <59> parac ) -Line <59> bracketc ] Line <59> newline -Line <59> newline -Line <60> string Inside a function! +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> bracketo [ -Line <64> name newblock -Line <64> colon : -Line <64> name function -Line <64> parao ( -Line <64> name a -Line <64> seperator , -Line <64> name b -Line <64> seperator , -Line <64> name c -Line <64> parac ) -Line <64> bracketc ] Line <64> newline Line <64> newline -Line <65> string Func Arguments: a = `a`, b = `b`, c = `c` +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 Time to return +Line <66> string Inside a function! Line <66> newline Line <66> newline -Line <67> ret -Line <67> name a -Line <67> plus + -Line <67> name b -Line <67> plus + -Line <67> name c Line <67> newline -Line <67> newline -Line <67> eof +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 [ diff --git a/DMS/test.dms b/DMS/test.dms index f68960a..8e812df 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -5,14 +5,14 @@ enable fullname enable forwardlabels // Do most of your labels exist ahead? enable savestate //enable leaking -enable debugging +//enable debugging loadfile "loadtest.dms" version 0.2 using extendedDefine [main] a1 = 10 b1 = 15 - print((a1!=b1)) + print("this" + " or " + "that") if(a==b){ print("Doing a test!") @@ -25,21 +25,28 @@ using extendedDefine print("This is an else!") } - if(a1!=10) this() | { + 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) - // for(x, 10, 1, -1){ - // print(x) - // } - if (this==that) this()|that() + if(a==nil) this()|that() + [this:function()] print("This") diff --git a/DMS/token.h b/DMS/token.h index 7725a2d..e39c60f 100644 --- a/DMS/token.h +++ b/DMS/token.h @@ -52,6 +52,7 @@ namespace dms::tokens { pipe, anglebracketO, anglebracketC, + escape, };//stream, t_vec, line, isNum, buffer struct token { tokentype type = noop; @@ -126,6 +127,7 @@ namespace dms::tokens { "pipe", "anglebracketO", "anglebracketC", + "escape" }; out << "Line <" << c.line_num << "> " << tokenlist[c.type] << " \t\t " << c.name; return out; diff --git a/DMS/value.cpp b/DMS/value.cpp index e21256a..8ccdb51 100644 --- a/DMS/value.cpp +++ b/DMS/value.cpp @@ -176,11 +176,11 @@ namespace dms { else if (lhs.type == datatypes::boolean && rhs.type == datatypes::boolean) { return value((bool)(lhs.b + rhs.b)); } - else if ((lhs.type == datatypes::string && !(rhs.type == nil)) || rhs.type == datatypes::string && !(lhs.type == nil)) { + else if ((lhs.type == datatypes::string || rhs.type == datatypes::string)) { return lhs.getPrintable() + rhs.getPrintable(); } else { - return value("Invalid use of '+'!", datatypes::error); + return "Invalid use of '+'"; } } value operator-(const value& lhs, const value& rhs) { @@ -404,6 +404,9 @@ namespace dms { else if (type == datatypes::error) { return std::string("ERROR: ") + s; } + else if (type == datatypes::escape) { + return ""; + } return "unknown"; } std::string value::toString() const { @@ -444,6 +447,9 @@ namespace dms { else if (c.type == datatypes::variable) { out << (char)c.type << c.s; // Do the lookup } + else if (c.type == datatypes::escape) { + out << (char)0; + } return out; }; // Fixed issue with memory not properly being cleaned up