Completed more cmds, getting close to the basic parsing

This commit is contained in:
Ryan Ward 2020-09-01 23:27:13 -04:00
parent 120ad85461
commit b9494b0803
28 changed files with 204 additions and 72 deletions

View File

@ -1,2 +1,2 @@
 LineParserParse.cpp
 LineParserMatchProcess.cpp
DMS.vcxproj -> F:\VSCWorkspace\DMS\Debug\DMS.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -13,6 +13,7 @@
#include "token.h"
#include "utils.h"
#include "Scope.h"
#include "errors.h"
#include <stack>
@ -56,10 +57,10 @@ namespace dms {
std::vector<tokens::token> temp;
std::vector<tokens::token> tdump;
size_t tabs = 0;
tokenstream* _stream;
dms_state* state;
tokenstream* _stream = nullptr;
dms_state* state = nullptr;
void doCheck(passer* stream, std::vector<tokens::token>* t_vec, size_t line, bool& isNum, bool& hasDec, std::vector<uint8_t>* buffer);
void _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();

View File

@ -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,6 +105,72 @@ 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)){
stream->next();
@ -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,6 +279,10 @@ namespace dms {
badSymbol(stream);
}
}
cmd* cc = current_chunk->cmds.back(); // Delete last element
current_chunk->cmds.pop_back();
delete cc;
if (hasfunc)
buildLabel(str);
return true;
}
@ -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);

View File

@ -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<token> tokens = stream.next(tokens::parac); // Consume until we see parac
stream->next(); // parao
std::vector<token> 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);
}

View File

@ -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<uint8_t> 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);

View File

@ -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] << " ";

View File

@ -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();
}

Binary file not shown.

View File

@ -10,5 +10,3 @@ namespace dms::number_utils {
dms_number* max(dms_state* state, dms_args args);
dms_number* pow(dms_state* state, dms_args args);
}

View File

@ -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

View File

@ -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;
}
};

View File

@ -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));

View File

@ -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<value*> args;

Binary file not shown.

Binary file not shown.

Binary file not shown.