diff --git a/DMS/Debug/DMS.log b/DMS/Debug/DMS.log index ae767a8..58b89fe 100644 --- a/DMS/Debug/DMS.log +++ b/DMS/Debug/DMS.log @@ -1,2 +1,2 @@ - LineParserParse.cpp + LineParserMatchProcess.cpp DMS.vcxproj -> F:\VSCWorkspace\DMS\Debug\DMS.exe diff --git a/DMS/Debug/DMS.obj b/DMS/Debug/DMS.obj index 74719e2..e28ff6d 100644 Binary files a/DMS/Debug/DMS.obj and b/DMS/Debug/DMS.obj differ diff --git a/DMS/Debug/DMS.tlog/CL.command.1.tlog b/DMS/Debug/DMS.tlog/CL.command.1.tlog index 1315fd4..7a1cb0f 100644 Binary files a/DMS/Debug/DMS.tlog/CL.command.1.tlog and b/DMS/Debug/DMS.tlog/CL.command.1.tlog differ diff --git a/DMS/Debug/DMS.tlog/CL.read.1.tlog b/DMS/Debug/DMS.tlog/CL.read.1.tlog index dcef754..2614eb1 100644 Binary files a/DMS/Debug/DMS.tlog/CL.read.1.tlog and b/DMS/Debug/DMS.tlog/CL.read.1.tlog differ diff --git a/DMS/Debug/DMS.tlog/CL.write.1.tlog b/DMS/Debug/DMS.tlog/CL.write.1.tlog index ce40db9..ff94f77 100644 Binary files a/DMS/Debug/DMS.tlog/CL.write.1.tlog and b/DMS/Debug/DMS.tlog/CL.write.1.tlog differ diff --git a/DMS/Debug/cmd.obj b/DMS/Debug/cmd.obj index 3302c22..0e15ae2 100644 Binary files a/DMS/Debug/cmd.obj and b/DMS/Debug/cmd.obj differ diff --git a/DMS/Debug/codes.obj b/DMS/Debug/codes.obj index 95e9400..2fd57f3 100644 Binary files a/DMS/Debug/codes.obj and b/DMS/Debug/codes.obj differ diff --git a/DMS/Debug/dms_exceptions.obj b/DMS/Debug/dms_exceptions.obj index dabdfc1..caa3db9 100644 Binary files a/DMS/Debug/dms_exceptions.obj and b/DMS/Debug/dms_exceptions.obj differ diff --git a/DMS/Debug/number_utils.obj b/DMS/Debug/number_utils.obj index 5ec87c4..7f91812 100644 Binary files a/DMS/Debug/number_utils.obj and b/DMS/Debug/number_utils.obj differ diff --git a/DMS/Debug/utils.obj b/DMS/Debug/utils.obj index e86b352..7ce3e1c 100644 Binary files a/DMS/Debug/utils.obj and b/DMS/Debug/utils.obj differ diff --git a/DMS/Debug/value.obj b/DMS/Debug/value.obj index cf1a83e..e02d89a 100644 Binary files a/DMS/Debug/value.obj and b/DMS/Debug/value.obj differ diff --git a/DMS/Debug/vc142.idb b/DMS/Debug/vc142.idb index f87c0ba..690da6c 100644 Binary files a/DMS/Debug/vc142.idb and b/DMS/Debug/vc142.idb differ diff --git a/DMS/Debug/vc142.pdb b/DMS/Debug/vc142.pdb index a93d702..bbcea6b 100644 Binary files a/DMS/Debug/vc142.pdb and b/DMS/Debug/vc142.pdb differ diff --git a/DMS/LineParser.h b/DMS/LineParser.h index 808701c..6ba9ff6 100644 --- a/DMS/LineParser.h +++ b/DMS/LineParser.h @@ -13,6 +13,7 @@ #include "token.h" #include "utils.h" #include "Scope.h" +#include "errors.h" #include @@ -56,10 +57,10 @@ namespace dms { std::vector temp; std::vector tdump; size_t tabs = 0; - tokenstream* _stream; - dms_state* state; + tokenstream* _stream = nullptr; + 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 _Parse(tokenstream* stream); // Match Process Code bool match_process_debug(tokenstream* stream); bool match_process_disp(tokenstream* stream); @@ -70,6 +71,7 @@ namespace dms { bool match_process_exit(tokenstream* stream); bool match_process_expression(tokenstream* stream, value* v); bool match_process_IFFF(tokenstream* stream); + bool match_process_assignment(tokenstream* stream); // Build void buildGoto(std::string g, bool v = false); void buildNoop(); diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index 8c26ea3..f8494eb 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -12,7 +12,6 @@ namespace dms { if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::string, tokens::newline)) { stream->next(); // Standard consumption std::string msg = stream->next().name; - print("DISP := ", msg); cmd* c = new cmd; c->opcode = codes::DISP; c->args.push(buildValue()); @@ -27,10 +26,9 @@ namespace dms { std::string name = stream->next().name; stream->next(); // That colon std::string msg = stream->next().name; - print("DISP := ", name, " says '", msg, "'"); cmd* c = new cmd; c->opcode = codes::DISP; - c->args.push(buildValue(name)); + c->args.push(buildVariable(name)); c->args.push(buildValue(msg)); current_chunk->addCmd(c); // Add the cmd to the current chunk // We might have to consume a newline... Depends on what's next @@ -45,7 +43,6 @@ namespace dms { // Command to set the speaker stream->next(); stream->next(); - print("Doing disp!!!"); while (stream->peek().type != tokens::cbracketc) { print(stream->peek()); if (stream->match(tokens::name)) { @@ -71,7 +68,12 @@ namespace dms { if (stream->match(tokens::string)) { cmd* c = new cmd; c->opcode = codes::DACT; - c->args.push(buildVariable(mode)); + c->args.push(buildValue(mode)); + current_chunk->addCmd(c); + // Now build the apnd msg cmd + c = new cmd; + c->opcode = codes::APND; + c->args.push(buildValue(stream->next().name)); current_chunk->addCmd(c); } else { @@ -80,7 +82,10 @@ namespace dms { } } else if (stream->match(tokens::string)) { - + cmd* c = new cmd; + c->opcode = codes::APND; + c->args.push(buildValue(stream->next().name)); + current_chunk->addCmd(c); } else if (stream->match(tokens::newline)) { stream->next(); @@ -100,8 +105,74 @@ namespace dms { return false; } + bool LineParser::match_process_assignment(tokenstream* stream) { + // something equals something else lets go + if (stream->match(tokens::name,tokens::equal)) { + value* var = buildVariable(stream->next().name); // The variable that we will be setting stuff to + stream->next(); // Consume the equal + cmd* c = new cmd; + c->opcode = codes::ASGN; + c->args.push(var); + if (stream->match(tokens::True)) { + stream->next(); + c->args.push(buildValue(true)); + current_chunk->addCmd(c); + return true; + } + else if (stream->match(tokens::False)) { + stream->next(); + c->args.push(buildValue(false)); + current_chunk->addCmd(c); + return true; + } + else if (stream->match(tokens::string)) { + c->args.push(buildValue(stream->next().name)); + current_chunk->addCmd(c); + return true; + } + else if (stream->match(tokens::nil)) { + stream->next(); + c->args.push(buildValue()); + current_chunk->addCmd(c); + return true; + } + else if (stream->match(tokens::number)) { + c->args.push(buildValue(std::stod(stream->next().name))); + current_chunk->addCmd(c); + return true; + } + else if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc)) { + // We are assigning a block as a variable + stream->next(); + c->args.push(buildBlock(stream->next().name)); + current_chunk->addCmd(c); + stream->next(); + return true; + } + else if (match_process_expression(stream,var)) { + // Expressions can internally set variables + // We actually need to clean up our cmds + current_chunk->cmds.pop_back(); + delete c; + return true; + } + else if (match_process_function(stream,var)) { + // Functions can internally set variables + // We actually need to clean up our cmds + current_chunk->cmds.pop_back(); + delete c; + return true; + } + else if (stream->match(tokens::name)) { + c->args.push(buildVariable(stream->next().name)); + current_chunk->addCmd(c); + return true; + } + } + return false; + } bool LineParser::match_process_debug(tokenstream* stream) { - if (stream->match(tokens::newline, tokens::debug, tokens::string) || stream->match(tokens::newline, tokens::debug, tokens::name)){ + if (stream-> match(tokens::newline, tokens::debug, tokens::string) || stream->match(tokens::newline, tokens::debug, tokens::name)){ stream->next(); stream->next(); if (state->isEnabled("debugging")) { @@ -139,6 +210,7 @@ namespace dms { c->args.push(buildValue(prompt)); current_chunk->addCmd(c); // We will keep a reference to this and add to it as we go through the list bool start = false; + bool hasfunc = false; /* What's going on here might be tough to understand just by looking at the code The bytecode generated by this code might look something like this: @@ -186,6 +258,7 @@ namespace dms { // We consumed the option now lets do some matching, note that all of these are one liners in the bytecode! if (match_process_function(stream,nullptr,false)) { // No returns and also no nesting of functions! // We cannot have a nested function here, but if we dont have that then we add our goto + hasfunc = true; buildGoto(str); } else if (match_process_goto(stream)) { @@ -206,7 +279,11 @@ namespace dms { badSymbol(stream); } } - buildLabel(str); + cmd* cc = current_chunk->cmds.back(); // Delete last element + current_chunk->cmds.pop_back(); + delete cc; + if (hasfunc) + buildLabel(str); return true; } return false; @@ -344,7 +421,7 @@ namespace dms { return false; } bool LineParser::match_process_goto(tokenstream* stream) { - if (stream->match(tokens::gotoo,tokens::name) || tokens::gotoo,tokens::string) { + if (stream->match(tokens::gotoo,tokens::name) || stream->match(tokens::gotoo,tokens::string)) { stream->next(); // consume gotoo if (stream->match(tokens::name)) { buildGoto(stream->next().name,true); diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index 9b166c4..4307da3 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -1,5 +1,4 @@ #include "LineParser.h" -#include "errors.h" using namespace dms::tokens; using namespace dms::utils; namespace dms { @@ -23,7 +22,7 @@ namespace dms { if (myfile.is_open()) { std::string line; - rawdata << ";;"; // For things to work I added 2 newlines. The issue is with how I decided to parse things. + rawdata << ";;"; // For things to work I added 2 newlines. Using ';' doesn't change the actual line numbers // This way you are allowed to start a block at the top of the screen! while (std::getline(myfile, line)) { trim(line); @@ -52,7 +51,7 @@ namespace dms { stream.next('\n'); // Seek until you find a newline } else if (data == '\n') { - doCheck(&stream, &t_vec, line-2, isNum, hasDec, &buffer); + doCheck(&stream, &t_vec, line, isNum, hasDec, &buffer); t_vec.push_back(token{ tokens::newline,codes::NOOP,"",line }); if (isNum) { t_vec.push_back(token{ tokens::number,codes::NOOP,stream.processBuffer(buffer),line }); @@ -297,13 +296,13 @@ namespace dms { } outputFile.close(); } - void LineParser::_Parse(tokenstream stream) { - token current = stream.next(); - while (stream.peek().type != tokens::eof) { + void LineParser::_Parse(tokenstream* stream) { + token current = stream->next(); + while (stream->peek().type != tokens::eof) { print(current); if (current.type == tokens::flag) { - temp = stream.next(tokens::newline); - stream.prev(); // Unconsume the newline piece + temp = stream->next(tokens::newline); + stream->prev(); // Unconsume the newline piece if (temp.size() != 2) { std::cout << "Error"; } @@ -337,20 +336,20 @@ namespace dms { } } // Default block - if (stream.match(tokens::newline,tokens::bracketo, tokens::name, tokens::bracketc)) { - stream.next(); - stream.next(); - std::string name = stream.next().name; + if (stream->match(tokens::newline,tokens::bracketo, tokens::name, tokens::bracketc)) { + stream->next(); + stream->next(); + std::string name = stream->next().name; 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 - else if (stream.match(tokens::newline, tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::bracketc)) { - stream.next(); - stream.next(); - std::string name = stream.next().name; - line = stream.next().line_num; - std::string temp = stream.next().name; + else if (stream->match(tokens::newline, tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::bracketc)) { + stream->next(); + stream->next(); + std::string name = stream->next().name; + line = stream->next().line_num; + std::string temp = stream->next().name; // Characters are a feature I want to have intergrated into the language if (temp == "char") { createBlock(name, bt_character); @@ -365,18 +364,18 @@ namespace dms { } } // Function block type - else if (stream.match(tokens::newline, tokens::bracketo, tokens::name, tokens::colon, tokens::name, tokens::parao)) { + else if (stream->match(tokens::newline, 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; + 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; if (b == "function") { createBlock(name, bt_method); // We have a method let's set the block type to that, but we aren't done yet // We need to set the params if any so the method can be supplied with arguments - stream.next(); // parao - std::vector tokens = stream.next(tokens::parac); // Consume until we see parac + stream->next(); // parao + std::vector tokens = stream->next(tokens::parac); // Consume until we see parac dms_args args; for (size_t i = 0; i < tokens.size() - 1; i++) {//The lase symbol is parac since that was the consume condition if (tokens[i].type == tokens::name) { @@ -405,27 +404,26 @@ namespace dms { } } // Control Handle all controls here - if (stream.match(tokens::control)) { - //token control = stream.next(); - if (match_process_choice(&stream)) { + if (stream->match(tokens::control)) { + //token control = stream->next(); + if (match_process_choice(stream)) { // Handle choice stuff } - else if (match_process_IFFF(&stream)) { + else if (match_process_IFFF(stream)) { // This will probably be the toughest one of them all } } // Displays both with a target and without - match_process_disp(&stream); // Match and process displays - if (stream.match(tokens::newline,tokens::label)) { // Match and process labels - stream.next(); - buildLabel(stream.next().name); + match_process_disp(stream); // Match and process dialogue + if (stream->match(tokens::newline,tokens::label)) { // Match and process labels + stream->next(); + buildLabel(stream->next().name); } - match_process_debug(&stream); - - //if (current.type != tokens::tab) // Old code for an old system... - // tabs = 0; - current = stream.next(); + match_process_assignment(stream); + match_process_debug(stream); + match_process_goto(stream); + current = stream->next(); } createBlock("$END$", bt_block); } diff --git a/DMS/LineParserUtils.cpp b/DMS/LineParserUtils.cpp index f137164..6ad050d 100644 --- a/DMS/LineParserUtils.cpp +++ b/DMS/LineParserUtils.cpp @@ -1,5 +1,4 @@ #include "LineParser.h" -#include "errors.h" using namespace dms::tokens; using namespace dms::utils; namespace dms { @@ -78,6 +77,7 @@ namespace dms { std::string passer::processBuffer(std::vector buf) { return std::string(buf.begin(), buf.end()); } + bool LineParser::isBlock() { return isBlock(bt_block); // Default block type } @@ -200,7 +200,7 @@ namespace dms { stream.init(&toks); _stream = &stream; this->state = state; // Grab the pointer to the state and store it within the parser object - _Parse(stream); + _Parse(&stream); } void LineParser::tolower(std::string &s1) { std::transform(s1.begin(), s1.end(), s1.begin(), std::tolower); diff --git a/DMS/cmd.h b/DMS/cmd.h index 9784d51..fe3a3b0 100644 --- a/DMS/cmd.h +++ b/DMS/cmd.h @@ -6,7 +6,7 @@ namespace dms { struct cmd { - dms::codes::op opcode; + dms::codes::op opcode = codes::NOOP; dms_args args; friend std::ostream& operator << (std::ostream& out, const cmd& c) { out << codes::list[c.opcode] << " "; diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index 53ef01a..aff0898 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -19,6 +19,7 @@ namespace dms { 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) { @@ -31,6 +32,7 @@ namespace dms { 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; } outputFile.close(); } diff --git a/DMS/dump.bin b/DMS/dump.bin index e69de29..b2d3f4a 100644 Binary files a/DMS/dump.bin and b/DMS/dump.bin differ diff --git a/DMS/number_utils.h b/DMS/number_utils.h index 863607a..1620dfa 100644 --- a/DMS/number_utils.h +++ b/DMS/number_utils.h @@ -9,6 +9,4 @@ namespace dms::number_utils { dms_number* abs(dms_state* state, dms_args args); dms_number* max(dms_state* state, dms_args args); dms_number* pow(dms_state* state, dms_args args); -} - - +} \ No newline at end of file diff --git a/DMS/test.dms b/DMS/test.dms index d640ab1..610dd1a 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -6,23 +6,72 @@ loadfile "loadtest.dms" version 1.2 using extendedDefine -[testblockpro] - "hehe" - [main] - Ryan: "This works!" + Bob: "Hi Ryan!" DEBUG "What's up" // Debug lines are removed when debug mode is disabled Ryan: { - true speed 100;calm "Hello Bob, " wait 0.455 excited "how are you doing?" // Becomes: Hello Bob, how are you doing? } + Bob: { + speed 50 + happy "You won't believe what just happened!" + } + Ryan: "Let me gue..." + Bob: { + speed 150 + excited "I got the job! " + "The pay is amazing, " + speed 50 + calm "but wait theres more!" + excited "I also get to go on a company trip and " + "I'm able to invite 2 friends to come along" + } + Ryan: { + happy "That's awesome! " + curious "Who do you plan on inviting?" + } + Bob: { + calm "Well you obviously, but I'm not sure who else I would want to bring..." + curious "Wanted to ask if you had any suggestions?" + } + Ryan: "Hmm, let me see..." + CHOICE "Who should I pick?" { + "Marie" goto "pickMarie" + "Sammy" goto "pickSammy" + "Ana" goto "pickAna" + "No Idea" goto "noIdea" + } + ::pickMarie:: + Ryan: "I think inviting Marie would be a good idea." + Bob: "I was actually thinking the same thing, let's invite her." + friend = [Marie] // Marie is a character block so obviously we set friend to a block + goto endpick + ::pickSammy:: + Ryan: "I think inviting Sammy would be a good idea." + Bob: "I haven't hung out with Sammy in too long, good pick." + friend = [Sammy] + goto endpick + ::pickAna:: + Ryan: "I think inviting Ana would be a good idea." + Bob: "Ana a name I haven't heard in a long time, sure sounds like a good time." + friend = [Ana] + goto endpick + ::noIdea:: + Ryan: "I really don't know who to bring..." + Bob: "Huh you having issues thinking of someone too. How about we bring Frank?" + Ryan: "Oh man Frank, for sure its been a minute since I last saw him." + friend = [Frank] + ::endpick:: + Bob: "Ill give ${friend} a call later!" + Ryan: "Sounds good looking forward to the trip!" + Bob: "Same, I'll send you the details later as well, see ya!" + Ryan: "Take care!" tester = "Hello" food = 3 - a = list[1] if statment { "test" @@ -46,12 +95,10 @@ using extendedDefine jump "overhere" hungry = (-2+4-((5*5)/sqrt(144+5)))^2*2+2 - list[1] = "Hello" var1 = func(1,"string", 2+5) a = 100 + func(1,"string", 2+5) + 100 func(1,"string", 2+5) ::mylabel:: - //Hello im testing stuff CHOICE "Pick one:" { "first" func(1,2,3) @@ -66,8 +113,6 @@ using extendedDefine "ten" exit 0 } - - [Bob:char] age = 24 money = 100 diff --git a/DMS/token.h b/DMS/token.h index 26b950b..eed80c2 100644 --- a/DMS/token.h +++ b/DMS/token.h @@ -52,7 +52,7 @@ namespace dms::tokens { };//stream, t_vec, line, isNum, buffer struct token { tokentype type = noop; - codes::op raw = codes::NOOP; + codes::op raw = codes::op::NOOP; std::string name=""; size_t line_num=0; void build(tokentype tt, codes::op o) { @@ -121,7 +121,7 @@ namespace dms::tokens { "ampersand", "nil" }; - out << "Line <" << c.line_num << ">" << codes::list[c.raw] << " " << tokenlist[c.type] << " \t\t " << c.name; + out << "Line <" << c.line_num << ">" << codes::list[(int)c.raw] << " " << tokenlist[c.type] << " \t\t " << c.name; return out; } }; diff --git a/DMS/value.cpp b/DMS/value.cpp index ce2aebd..172118f 100644 --- a/DMS/value.cpp +++ b/DMS/value.cpp @@ -39,6 +39,12 @@ namespace dms { std::string val = utils::concat("$",count); return buildVariable(val); } + value* buildBlock(std::string str) { + value* val = new value{}; + val->set(buildString(str)); + val->type = block; + return val; + } value* buildVariable(std::string str) { value* val = new value{}; val->set(buildString(str)); diff --git a/DMS/value.h b/DMS/value.h index 9abc779..f934177 100644 --- a/DMS/value.h +++ b/DMS/value.h @@ -6,7 +6,7 @@ namespace dms { struct dms_env; - enum datatypes { nil, number, boolean, env, string, custom, variable }; + enum datatypes { nil, number, boolean, env, string, custom, variable, block }; struct dms_number { double val; double getValue() { return val; } @@ -77,6 +77,9 @@ namespace dms { else if (c.type == custom) { out << (char)c.type << "Custom Data: " << c; } + else if (c.type == block) { + out << (char)c.type << c.s->getValue(); + } // Internal kinda else if (c.type == datatypes::variable) { out << (char)c.type << c.s->getValue(); // Do the lookup @@ -91,6 +94,7 @@ namespace dms { value* buildValue(double dbl); value* buildValue(int i); value* buildValue(bool b); + value* buildBlock(std::string str); struct dms_args { std::vector args; diff --git a/Debug/DMS.exe b/Debug/DMS.exe index 80aad85..19ba0f9 100644 Binary files a/Debug/DMS.exe and b/Debug/DMS.exe differ diff --git a/Debug/DMS.ilk b/Debug/DMS.ilk index 7d5047c..0273394 100644 Binary files a/Debug/DMS.ilk and b/Debug/DMS.ilk differ diff --git a/Debug/DMS.pdb b/Debug/DMS.pdb index 5f0d37f..550d803 100644 Binary files a/Debug/DMS.pdb and b/Debug/DMS.pdb differ