diff --git a/DMS syntax npp.xml b/DMS syntax npp.xml
index 098ae4d..67e0893 100644
--- a/DMS syntax npp.xml
+++ b/DMS syntax npp.xml
@@ -25,9 +25,9 @@
ENABLE DISABLE LOADFILE ENTRY USING VERSION as AS enable disable loadfile entry using version
- if then return and or true false for while choice end else elseif goto
+ if then return and or true false for while choice end else elseif goto jump exit
leaking debugging warnings statesave hostmsg
- ceil tan CSIM log10 sinh GOTOE lshift deg MUL QUIT cosh exp rad GOTO SUB log ADD JUMP error POW randomseed floor tanh max atan SKIP acos DIV abs rshif COMPARE print atan2 asin cos sin mod sqrt function getInput sleep getVar setVar newThread setGlobalVar getGlobalVar SAVE LOAD WATCH env char
+ ceil tan CSIM log10 sinh GOTOE lshift deg MUL QUIT cosh exp rad GOTO SUB log ADD error POW randomseed floor tanh max atan SKIP acos DIV abs rshif COMPARE print atan2 asin cos sin mod sqrt function getInput sleep getVar setVar newThread setGlobalVar getGlobalVar SAVE LOAD WATCH env char
_VERSION
filesystem extendedDefine
@@ -35,30 +35,30 @@
00:: 01 02:: 03$ 04 05$ 06" 07\ 08" 09 10 11 12' 13 14' 15 16 17 18 19 20 21 22 23
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DMS/DMS.cpp b/DMS/DMS.cpp
index 8b5d578..4542ee8 100644
--- a/DMS/DMS.cpp
+++ b/DMS/DMS.cpp
@@ -22,5 +22,4 @@ int main()
{
LineParser parser = LineParser("test.dms");
parser.Parse();
- print("Goodbye!");
}
\ No newline at end of file
diff --git a/DMS/DMS.vcxproj b/DMS/DMS.vcxproj
index b86a06e..b188331 100644
--- a/DMS/DMS.vcxproj
+++ b/DMS/DMS.vcxproj
@@ -147,6 +147,7 @@
+
diff --git a/DMS/DMS.vcxproj.filters b/DMS/DMS.vcxproj.filters
index b075295..af03e5d 100644
--- a/DMS/DMS.vcxproj.filters
+++ b/DMS/DMS.vcxproj.filters
@@ -54,6 +54,9 @@
Source Files\DMS
+
+ Source Files\DMS
+
diff --git a/DMS/LineParser.cpp b/DMS/LineParser.cpp
index cd58498..2f5dc62 100644
--- a/DMS/LineParser.cpp
+++ b/DMS/LineParser.cpp
@@ -1,5 +1,5 @@
#include "LineParser.h"
-
+#include "errors.h"
using namespace dms::tokens;
using namespace dms::utils;
namespace dms {
@@ -77,6 +77,9 @@ namespace dms {
return isBlock(bt_block); // Default block type
}
bool LineParser::isBlock(blocktype bk_type) {
+ if (current_chunk == nullptr) {
+ return false; // If a chunk wasn't defined then code was probably defined outside of a block
+ }
return current_chunk->type == bk_type;
}
void doCheck(passer* stream,std::vector* t_vec, size_t line, bool &isNum, bool &hasDec, std::vector* buffer) {
@@ -177,8 +180,8 @@ namespace dms {
}
bool LineParser::createBlock(std::string bk_name, blocktype bk_type) {
if (current_chunk != nullptr) {
- if (!chunks.count(current_chunk->name))
- chunks.insert_or_assign(current_chunk->name, current_chunk);
+ if (!state->chunks.count(current_chunk->name))
+ state->chunks.insert_or_assign(current_chunk->name, current_chunk);
else
{
std::stringstream str;
@@ -192,13 +195,12 @@ namespace dms {
chunk_type = bk_type;
current_chunk->type = bk_type;
print("Created Block: ",bk_name," <",bk_type,">");
+ return true;
}
void LineParser::_Parse(tokenstream stream) {
token current = stream.next();
while (stream.peek().type != tokens::eof) {
print(current);
- if (current.type == tokens::tab)
- tabs++;
if (current.type == tokens::flag) {
temp = stream.next(tokens::newline);
stream.prev(); // Unconsume the newline piece
@@ -225,7 +227,9 @@ namespace dms {
// TODO add usings, kinda useless atm since everything will be packed in. Perhaps extensions?
}
else if (code == codes::LOAD && tok == tokens::string) {
- Parse(state, temp[0].name); // Load another file
+ print("Loading File: ",temp[0].name);
+ LineParser parser = LineParser();
+ parser.Parse(state, temp[0].name);// Load another file
}
else {
std::stringstream str;
@@ -239,7 +243,6 @@ namespace dms {
std::string name = stream.next().name;
createBlock(name,bt_block);
line = stream.next().line_num; // Consume
- stream.next(); // 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)) {
@@ -260,7 +263,6 @@ 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)) {
@@ -303,40 +305,89 @@ namespace dms {
}
}
// Control Handle all controls here
- if (stream.match(tokens::tab, tokens::control)) {
- stream.next(); // Standard consumption
+ if (stream.match(tokens::control)) {
token control = stream.next();
if (control.raw == codes::CHOI && stream.peek().type == tokens::string) {
// Let's parse choice blocks.
std::string prompt = stream.next().name;
print("Prompt: ", prompt);
bool good = true;
- size_t c = 0;
- while (good) {
- // We need to template the matches
- if (stream.match(tokens::tab, tokens::string, tokens::name, tokens::parao)) {
- stream.next();
- std::string prompt = stream.next().name;
+ std::string option;
+ cmd* c = new cmd;
+ // Create a unique label name by using the line number
+ std::string choicelabel = concat("$CHOI_END_", stream.peek().line_num);
+ wait();
+ c->opcode = codes::CHOI;
+ 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
- // To handle the function stuff we need to consume and process that data
- // We have a method to process function data since this will be used a lot in many different places
- // We just grabbed the prompt, we don't yet know how many choices we have. So we have to figure out how we can
- // Process and write the bytecode for this.
- std::string func = stream.next().name;
- print("Choice: <", c, "> ", prompt, " Funcname: ", func);
- std::vector funcstuff = stream.next(tokens::newline);
+ /*
+ 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:
- //We need to process the function data and finish creating
+ off op opcodes
+ 0 CHOI "Pick one!" "Choice 1" "Choice 2" "Choice 3" "Choice 4"
+ 1 FUNC print "You picked 1!"
+ 2 GOTO $CHOI_END_1
+ 3 FUNC print "You picked 2!"
+ 4 GOTO $CHOI_END_1
+ 5 JUMP park
+ 6 NOOP
+ 7 GOTO mylabel
+ 8 LABL $CHOI_END_1
- c++;
+ The CHOI code tells the vm that we need to process user input. The input we get in a number 0-3
+ I know we have 4 choices
+ If the user provides us with a 0 then we need to move to off 1
+ If the user provides us with a 1 then we need to move to off 3
+ If the user provides us with a 2 then we need to move to off 5
+ If the user provides us with a 3 then we need to move to off 7
+ I'm sure you see the pattern here. 1 (+2) 3 (+2) 5... We only need to jump once then let the vm continue like normal.
+ The math for this is: [current_pos] + (n*2+1)
+ n*2+1 (n = 0) = 1
+ n*2+1 (n = 1) = 3
+ n*2+1 (n = 2) = 5
+ n*2+1 (n = 3) = 7
+ Which is why you see NOOP for the JUMP code. If GOTO wasn't the last choice possible to make there would be a NOOP after that as well.
+ The NOOP ensures the pattern stays.
+ If we are provided with a number greater than 3 then we can push an execption.
+ */
+ while (!stream.match(tokens::cbracketc)) {
+ // We need to match the possible options for a choice block
+ /*
+ "option" function()
+ "option" goto ""
+ "option" goto var
+ "option" jump ""
+ "option" jump var
+ "option" exit [0]
+
+ Exit takes an optional int
+ */
+ if (stream.match(tokens::string)) {
+ std::string name = stream.next().name;
+ c->args.push(buildValue(name)); // We append the choice to the first part of the CHOI cmd
+
+ // 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)) {
+
+ }
+ else if (match_process_goto(&stream)) {
+
+ }
+ else if (match_process_jump(&stream)) {
+
+ }
+ else if (match_process_exit(&stream)) {
+
+ }
}
- else if (stream.match(tokens::tab) || stream.match(tokens::newline)) {
- stream.next(); // Allow tabs and newlines to pass like normal
+ // Last Match
+ else if (stream.match(tokens::newline)) {
+ stream.next(); // Consume
}
- else {
- good = false;
- print("Choice handled!");
- wait();
+ else if (!stream.match(tokens::cbracketc)) {
+ state->push_error(errors::error{errors::choice_unknown,"Unexpected symbol!"});
}
}
}
@@ -345,26 +396,8 @@ namespace dms {
}
}
// Displays both with a target and without
- if (stream.match(tokens::tab, tokens::string, tokens::newline)) {
- // ToDo Implement the command for this
- stream.next(); // Standard consumption
- print("DISP := ", stream.next().name);
- }
- else if (stream.match(tokens::tab, tokens::name, tokens::colon, tokens::string, tokens::newline)) {
- // We might have to handle scope here
- // Here we mathc Name "This guy said this!"
- stream.next(); // Standard consumption
- std::string name = stream.next().name;
- stream.next(); // That colon
- std::string msg = stream.next().name;
- print("DISP := ", name, " says '", msg, "'");
- // We might have to consume a newline... Depends on what's next
- if (stream.hasScope(tabs)) {
- // If true we might have a group of displaying stuff.
- // A proper scope will have the next line contain one more tab than the last
+ match_process_disp(&stream);
- }
- }
// function stuff
/*if (match(stream, tokens::name, tokens::parao)) {
std::string n = stream.next().name;
@@ -379,9 +412,10 @@ namespace dms {
tabs = 0;
current = stream.next();
}
- chunks.insert_or_assign(current_chunk->name, current_chunk);
+ state->chunks.insert_or_assign(current_chunk->name, current_chunk);
}
void LineParser::tokenizer(dms_state* state,std::vector &toks) {
+ tokenstream stream;
stream.init(&toks);
this->state = state; // Grab the pointer to the state and store it within the parser object
_Parse(stream);
@@ -414,7 +448,10 @@ namespace dms {
if (myfile.is_open())
{
std::string line;
+ rawdata << "\n\n"; // For things to work I added 2 newlines. The issue is with how I decided to parse things.
+ // This way you are allowed to start a block at the top of the screen!
while (std::getline(myfile, line)) {
+ trim(line);
rawdata << line << "\n";
}
myfile.close();
@@ -550,6 +587,10 @@ namespace dms {
doCheck(&stream, &t_vec, line, isNum, hasDec, &buffer);
t_vec.push_back(token{ tokens::colon,codes::NOOP,"",line });
}
+ else if (data == ';') {
+ doCheck(&stream, &t_vec, line, isNum, hasDec, &buffer);
+ t_vec.push_back(token{ tokens::newline,codes::NOOP,"",line });
+ }
else if (data == '!') {
doCheck(&stream, &t_vec, line, isNum, hasDec, &buffer);
t_vec.push_back(token{ tokens::Not,codes::NOOP,"",line });
diff --git a/DMS/LineParser.h b/DMS/LineParser.h
index 046c846..0ed5c01 100644
--- a/DMS/LineParser.h
+++ b/DMS/LineParser.h
@@ -43,19 +43,26 @@ namespace dms {
class LineParser
{
std::string fn;
- std::map chunks;
chunk* current_chunk = nullptr;
std::string chunk_name;
blocktype chunk_type = bt_block;
std::stack scopes;
size_t line = 1;
- tokenstream stream;
std::vector temp;
size_t tabs = 0;
dms_state* state;
void _Parse(tokenstream stream);
+ // Match Process Code
+ bool match_process_debug(tokenstream* stream);
+ bool match_process_disp(tokenstream* stream);
+ bool match_process_choice(tokenstream* stream);
+ bool match_process_function(tokenstream* stream);
+ bool match_process_goto(tokenstream* stream);
+ bool match_process_jump(tokenstream* stream);
+ bool match_process_exit(tokenstream* stream);
public:
+ //Refer to streams.cpp for the match_process_CMD code.
dms_state* Parse();
dms_state* Parse(std::string l);
dms_state* Parse(dms_state* state, std::string l);
diff --git a/DMS/LineParserExtended.cpp b/DMS/LineParserExtended.cpp
new file mode 100644
index 0000000..1fd11d8
--- /dev/null
+++ b/DMS/LineParserExtended.cpp
@@ -0,0 +1,63 @@
+#include "LineParser.h"
+using namespace dms::tokens;
+using namespace dms::utils;
+namespace dms {
+ bool LineParser::match_process_disp(tokenstream* stream) {
+ /*
+ DISP, "msg"
+ DISP, "msg" speaker
+
+ Compound DISP
+ */
+ if (isBlock(bt_block) && 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(msg));
+ current_chunk->addCmd(c); // Add the cmd to the current chunk
+ return true;
+ }
+ else if (isBlock(bt_block) && stream->match(tokens::newline, tokens::name, tokens::colon, tokens::string, tokens::newline)) {
+ // We might have to handle scope here
+ // Here we match 'Ryan: "This guy said this!"' Note the colon is needed!
+ stream->next(); // Standard consumption
+ 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(msg));
+ c->args.push(buildValue(name));
+ current_chunk->addCmd(c); // Add the cmd to the current chunk
+ // We might have to consume a newline... Depends on what's next
+ return true;
+ }
+ // emotion: "path"
+ // looks like a simple disp command
+ else if (isBlock(bt_character) && stream->match(tokens::tab, tokens::name, tokens::colon, tokens::string, tokens::newline)) {
+ return true;
+ }
+ return false;
+ }
+ bool LineParser::match_process_debug(tokenstream* stream) {
+ return false;
+ }
+ bool LineParser::match_process_choice(tokenstream* stream) {
+ return false;
+ }
+ bool LineParser::match_process_function(tokenstream* stream) {
+ return false;
+ }
+ bool LineParser::match_process_goto(tokenstream* stream) {
+ return false;
+ }
+ bool LineParser::match_process_jump(tokenstream* stream) {
+ return false;
+ }
+ bool LineParser::match_process_exit(tokenstream* stream) {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/DMS/chunk.cpp b/DMS/chunk.cpp
index a5666e4..9a9dab3 100644
--- a/DMS/chunk.cpp
+++ b/DMS/chunk.cpp
@@ -1,6 +1,6 @@
#include "chunk.h"
namespace dms {
- void chunk::addCmd(cmd c) {
+ void chunk::addCmd(cmd* c) {
cmds.push_back(c);
}
}
\ No newline at end of file
diff --git a/DMS/chunk.h b/DMS/chunk.h
index d154a67..cfc2c94 100644
--- a/DMS/chunk.h
+++ b/DMS/chunk.h
@@ -14,10 +14,11 @@ namespace dms {
blocktype type = bt_block;
dms_args params;
std::string name = "";
- std::vector cmds = std::vector();
+ std::vector cmds;
size_t pos = 0;
size_t line = 0;
- void addCmd(cmd c);
+ void addCmd(cmd* c);
+ chunk(){}
};
}
diff --git a/DMS/dms_state.h b/DMS/dms_state.h
index 627f246..515c6af 100644
--- a/DMS/dms_state.h
+++ b/DMS/dms_state.h
@@ -1,7 +1,7 @@
#pragma once
-#include
#include "errors.h"
-#include