ITS WORKING HOLY SHIT
This commit is contained in:
parent
e182ffc14a
commit
084acbba1e
9 changed files with 237 additions and 131 deletions
|
@ -4,7 +4,7 @@
|
||||||
"name": "x64-Debug",
|
"name": "x64-Debug",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
"cmakeCommandArgs": "",
|
"cmakeCommandArgs": "",
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
cmake_minimum_required (VERSION 3.8)
|
cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
# Add source to this project's executable.
|
# Add source to this project's executable.
|
||||||
add_executable (NouVeL "NouVeL.cpp" "NVL.cpp")
|
add_executable (NouVeL "NouVeL.cpp" "Parser.cpp" "Environment.cpp" "Environment.h")
|
||||||
|
|
||||||
# TODO: Add tests and install targets if needed.
|
# TODO: Add tests and install targets if needed.
|
||||||
|
|
51
NouVeL/Environment.cpp
Normal file
51
NouVeL/Environment.cpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
#include <any>
|
||||||
|
#include <variant>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "Environment.h"
|
||||||
|
|
||||||
|
namespace NVL {
|
||||||
|
const unsigned LOG_SIZE = 50;
|
||||||
|
|
||||||
|
bool Variable::operator==(const Variable& other) const {
|
||||||
|
if (other.type != type)
|
||||||
|
return false;
|
||||||
|
switch (type) {
|
||||||
|
case Type::Number:
|
||||||
|
return std::get<Number>(other.value) == std::get<Number>(value);
|
||||||
|
case Type::String:
|
||||||
|
return std::get<std::string>(other.value) == std::get<std::string>(value);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Variable::Variable() {}
|
||||||
|
Variable::Variable(const Number& v) : type(Type::Number), value(v), length(1) {}
|
||||||
|
Variable::Variable(const std::string& v) : type(Type::String), value(v), length(1) {}
|
||||||
|
Variable::Variable(const std::vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
|
||||||
|
Variable::Variable(void* v, int l) : type(Type::Procedure), value(v), length(l) {}
|
||||||
|
|
||||||
|
Environment ENVIRONMENT;
|
||||||
|
|
||||||
|
void Environment::enter(const std::string& name, Variable p) {
|
||||||
|
if (env.find(name) != env.end())
|
||||||
|
throw std::runtime_error("Redefinition of symbol in environment");
|
||||||
|
env[name] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Environment::set(const std::string& name, Variable p) {
|
||||||
|
if (env.find(name) == env.end())
|
||||||
|
throw std::runtime_error("Attempting to set undefined variable");
|
||||||
|
env[name] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable Environment::get(const std::string& name) {
|
||||||
|
return env.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Environment::exists(const std::string& name) {
|
||||||
|
return env.find(name) != env.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
NouVeL/Environment.h
Normal file
33
NouVeL/Environment.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
#include <any>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
namespace NVL {
|
||||||
|
using Number = float;
|
||||||
|
enum class Type { Procedure, Number, String, Array };
|
||||||
|
|
||||||
|
struct Variable {
|
||||||
|
Type type;
|
||||||
|
std::variant<Number, std::string, std::vector<Variable>, void*> value;
|
||||||
|
int length;
|
||||||
|
bool operator==(const Variable& other) const;
|
||||||
|
Variable();
|
||||||
|
Variable(const Number& v);
|
||||||
|
Variable(const std::string& v);
|
||||||
|
Variable(const std::vector<Variable>& v);
|
||||||
|
Variable(void* v, int l);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Environment {
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, Variable> env{};
|
||||||
|
public:
|
||||||
|
void enter(const std::string& name, Variable p);
|
||||||
|
void set(const std::string& name, Variable p);
|
||||||
|
Variable get(const std::string& name);
|
||||||
|
bool exists(const std::string& name);
|
||||||
|
};
|
||||||
|
extern Environment ENVIRONMENT;
|
||||||
|
}
|
|
@ -1,8 +1,16 @@
|
||||||
#include "NVL.h"
|
#include "Parser.h"
|
||||||
|
#include "Environment.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <any>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
auto f = [](std::string& what) -> std::any { return true; };
|
||||||
|
NVL::Variable v(&f, 3);
|
||||||
|
|
||||||
|
NVL::ENVIRONMENT.enter("hello", v);
|
||||||
|
|
||||||
const std::string PJ_DIR = "E:\\Archive\\Projects\\NouVeL\\NouVeL\\";
|
const std::string PJ_DIR = "E:\\Archive\\Projects\\NouVeL\\NouVeL\\";
|
||||||
NVL::ParseFile(PJ_DIR + "test.nvl");
|
NVL::ParseFile(PJ_DIR + "test.nvl");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <functional>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "SymbolConfig.h"
|
#include "Environment.h"
|
||||||
|
|
||||||
|
|
||||||
const unsigned LOG_SIZE = 50;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct ParseGroup {
|
struct ParseGroup {
|
||||||
std::string accept;
|
std::string accept;
|
||||||
|
|
||||||
|
operator std::string() const {
|
||||||
|
return accept;
|
||||||
|
}
|
||||||
|
constexpr bool operator== (const std::string& other) const {
|
||||||
|
return accept == other;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Match {
|
struct Match {
|
||||||
|
@ -48,13 +51,19 @@ namespace {
|
||||||
const ParseGroup SYMBOL = { ALPHA.accept + NUMERIC.accept + "_-" };
|
const ParseGroup SYMBOL = { ALPHA.accept + NUMERIC.accept + "_-" };
|
||||||
const ParseGroup WS = { " \t\v\f\r\n" };
|
const ParseGroup WS = { " \t\v\f\r\n" };
|
||||||
const ParseGroup SEPARATOR = {
|
const ParseGroup SEPARATOR = {
|
||||||
WS.accept + char(ARRAY_OPEN) + char(ARRAY_CLOSE) + char(GROUP_OPEN) + char(GROUP_CLOSE)
|
WS.accept +
|
||||||
|
char(ARRAY_OPEN) +
|
||||||
|
char(ARRAY_CLOSE) +
|
||||||
|
char(GROUP_OPEN) +
|
||||||
|
char(GROUP_CLOSE) +
|
||||||
|
char(ARRAY_DELIM) +
|
||||||
|
char(COMMENT_BEGIN)
|
||||||
};
|
};
|
||||||
const Match NEWLINE = { "\n" };
|
const Match NEWLINE = { "\n" };
|
||||||
const Match ESCAPE = { "\\" };
|
const Match ESCAPE = { "\\" };
|
||||||
const ParseGroup ESCAPED = { "\\\"" };
|
const ParseGroup ESCAPED = { "\\\"" };
|
||||||
|
|
||||||
enum class Type { Symbol, Number, String, Array };
|
enum class ParseType { Symbol, Number, String, Array, Subexpression };
|
||||||
|
|
||||||
std::string read_file_to_string(const std::string& path) {
|
std::string read_file_to_string(const std::string& path) {
|
||||||
std::ifstream f(path);
|
std::ifstream f(path);
|
||||||
|
@ -67,8 +76,7 @@ namespace {
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int prev = 0;
|
int prev = 0;
|
||||||
while ((pos = str.find(NEWLINE.accept[0], prev)) != std::string::npos)
|
while ((pos = str.find(NEWLINE, prev)) != std::string::npos) {
|
||||||
{
|
|
||||||
lines.push_back(str.substr(prev, pos - prev));
|
lines.push_back(str.substr(prev, pos - prev));
|
||||||
prev = pos + 1;
|
prev = pos + 1;
|
||||||
}
|
}
|
||||||
|
@ -94,56 +102,28 @@ namespace {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ParseState { Root, Scene, Command, Dialogue, String, Array };
|
/*struct Command {
|
||||||
|
Object procedure;
|
||||||
using NVL_Number = float;
|
std::vector<Object> args{};
|
||||||
|
};*/
|
||||||
struct Environment {
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, void*> env;
|
|
||||||
public:
|
|
||||||
void enter(const std::string& name, void* p) {
|
|
||||||
if (env.find(name) != env.end())
|
|
||||||
throw std::runtime_error("Redefinition of symbol in environment");
|
|
||||||
env[name] = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(const std::string& name, void* p) {
|
|
||||||
if (env.find(name) == env.end())
|
|
||||||
throw std::runtime_error("Attempting to set undefined variable");
|
|
||||||
env[name] = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto get(const std::string& name) {
|
|
||||||
return env.at(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool exists(const std::string& name) {
|
|
||||||
return env.find(name) != env.end();
|
|
||||||
}
|
|
||||||
} ENV;
|
|
||||||
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
Type type;
|
ParseType type;
|
||||||
std::variant<
|
std::variant<
|
||||||
NVL_Number,
|
NVL::Number,
|
||||||
std::string,
|
std::string,
|
||||||
std::vector<Object>
|
std::vector<Object>
|
||||||
> value;
|
> value;
|
||||||
};
|
};
|
||||||
|
using Command = std::vector<Object>;
|
||||||
|
|
||||||
struct Command {
|
|
||||||
Object procedure;
|
|
||||||
std::vector<Object> args{};
|
|
||||||
};
|
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<Command> commands{};
|
std::vector<Command> commands{};
|
||||||
public:
|
public:
|
||||||
Scene(const std::string& name) : name(name) {
|
Scene(const std::string& name) : name(name) {
|
||||||
ENV.enter(name, this);
|
//NVL::ENVIRONMENT.enter(name, this);
|
||||||
}
|
}
|
||||||
void append(const Command& c) {
|
void append(const Command& c) {
|
||||||
commands.push_back(c);
|
commands.push_back(c);
|
||||||
|
@ -169,6 +149,11 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkipOverFirstChar(const std::string& f, size_t& pos) {
|
||||||
|
SkipWS(f, pos);
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetToken(const std::string& f, size_t& pos) {
|
std::string GetToken(const std::string& f, size_t& pos) {
|
||||||
SkipWS(f, pos);
|
SkipWS(f, pos);
|
||||||
auto start = pos;
|
auto start = pos;
|
||||||
|
@ -189,7 +174,7 @@ namespace {
|
||||||
return f.substr(start, pos - start);
|
return f.substr(start, pos - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSymbol(const std::string& token) {
|
bool IsLegalSymbolName(const std::string& token) {
|
||||||
if (ALPHA.accept.find(token[0]) == std::string::npos)
|
if (ALPHA.accept.find(token[0]) == std::string::npos)
|
||||||
return false;
|
return false;
|
||||||
for (auto& i : token)
|
for (auto& i : token)
|
||||||
|
@ -197,47 +182,41 @@ namespace {
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void ParseArray(ParseState& state, const std::string& f, size_t& pos, Command& command) {
|
|
||||||
SkipWS(f, pos);
|
|
||||||
/*
|
|
||||||
// Read until array end OR end of line, state wont change if array end was not found
|
|
||||||
auto start = pos;
|
|
||||||
while (pos < line.length()) {
|
|
||||||
if (ARRAY_OPEN.accept[0] == line[pos])
|
|
||||||
parse.layer++;
|
|
||||||
else if (ARRAY_CLOSE.accept[0] == line[pos])
|
|
||||||
break;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
parse.parse = line.substr(start, pos++ - start);
|
|
||||||
|
|
||||||
if (parse.parse.back() == ARRAY_CLOSE.accept[0]) {
|
Object ParseExpression(const std::string& f, size_t& pos);
|
||||||
parse.layer--;
|
Object ParseArray(const std::string& f, size_t& pos, int layer) {
|
||||||
if (parse.layer == 0) {
|
SkipComments(f, pos);
|
||||||
|
|
||||||
}
|
std::vector<Object> array{};
|
||||||
|
|
||||||
|
array.push_back(ParseExpression(f, pos));
|
||||||
|
while (PeekToken(f, pos)[0] != ARRAY_CLOSE) {
|
||||||
|
if (PeekToken(f, pos)[0] == ARRAY_DELIM)
|
||||||
|
SkipOverFirstChar(f, pos);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Invalid array member");
|
||||||
|
array.push_back(ParseExpression(f, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return { ParseType::Array, array };
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ParseString(ParseState& state, const std::string& f, size_t& pos) {
|
std::string ParseString(const std::string& f, size_t& pos) {
|
||||||
SkipWS(f, pos);
|
SkipComments(f, pos);
|
||||||
std::vector<int> discards{};
|
std::vector<int> discards{};
|
||||||
auto start = ++pos; // skip opening quote
|
auto start = ++pos; // skip opening quote
|
||||||
do {
|
do {
|
||||||
if (f[pos] == char(QUOTE)) {
|
if (f[pos] == QUOTE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (f[pos] == char(ESCAPE)) {
|
else if (f[pos] == ESCAPE) {
|
||||||
if (ESCAPED.accept.find(f[pos]) != std::string::npos) {
|
if (ESCAPED.accept.find(f[pos]) != std::string::npos) {
|
||||||
discards.push_back(pos++);
|
discards.push_back(pos++);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Unrecognized escape sequence");
|
throw std::runtime_error("Unrecognized escape sequence");
|
||||||
}
|
}
|
||||||
else if (f[pos] == char(NEWLINE)) {
|
else if (f[pos] == NEWLINE) {
|
||||||
throw std::runtime_error("Unclosed String");
|
throw std::runtime_error("Unclosed String");
|
||||||
}
|
}
|
||||||
} while (pos++);
|
} while (pos++);
|
||||||
|
@ -247,74 +226,110 @@ namespace {
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
unsigned GetProcedureArity(const std::string& key) {
|
||||||
// Handles dialogue as well
|
return NVL::ENVIRONMENT.get(key).length;
|
||||||
void ParseCommand(ParseState& state, const std::string& f, size_t& pos, Scene& scene) {
|
|
||||||
int initial = pos; // TEMP
|
|
||||||
|
|
||||||
int exp_layer = 0;
|
|
||||||
bool exp_complete = false;
|
|
||||||
|
|
||||||
auto proc = GetToken(f, pos);
|
|
||||||
if (!IsSymbol(proc)) throw std::runtime_error("Illegal Procedure name");
|
|
||||||
|
|
||||||
Command c{ { Type::Symbol, proc }, {} };
|
|
||||||
while (!exp_complete) {
|
|
||||||
SkipComments(f, pos);
|
|
||||||
if (pos > f.find('\n', initial)) // TEMP
|
|
||||||
exp_complete = true; // TEMP
|
|
||||||
auto t = PeekToken(f, pos);
|
|
||||||
if (t[0] == ARRAY_OPEN) {
|
|
||||||
state = ParseState::Array;
|
|
||||||
ParseArray(state, f, pos, c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (t[0] == GROUP_OPEN) {
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (t[0] == GROUP_CLOSE) {
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (t[0] == QUOTE) {
|
|
||||||
state = ParseState::String;
|
|
||||||
c.args.push_back(Object{ Type::String, ParseString(state, f, pos) });
|
|
||||||
}
|
|
||||||
else if (t[0] == ARRAY_CLOSE)
|
|
||||||
throw std::runtime_error("Cannot match array");
|
|
||||||
else {
|
|
||||||
auto token = GetToken(f, pos);
|
|
||||||
if (IsNumeric(token)) {
|
|
||||||
c.args.push_back(Object{ Type::Number, std::stof(token) });
|
|
||||||
}
|
|
||||||
else if (IsSymbol(token)) {
|
|
||||||
c.args.push_back(Object{ Type::Symbol, token });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::runtime_error("Illegal symbol");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scene.append(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseScene(ParseState& state, const std::string& f, size_t& pos, std::vector<Scene>& scenes) {
|
Command ParseCommand(const std::string& f, size_t& pos) {
|
||||||
|
SkipComments(f, pos);
|
||||||
|
|
||||||
|
auto proc = GetToken(f, pos);
|
||||||
|
|
||||||
|
if (!IsLegalSymbolName(proc)) throw std::runtime_error("Illegal Procedure name");
|
||||||
|
Command c{ Object{ ParseType::Symbol, proc } };
|
||||||
|
for (int i = 0; i < GetProcedureArity(proc); i++) {
|
||||||
|
c.push_back(ParseExpression(f, pos));
|
||||||
|
};
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object ParseExpression(const std::string& f, size_t& pos) {
|
||||||
|
SkipComments(f, pos);
|
||||||
|
|
||||||
|
auto t = PeekToken(f, pos);
|
||||||
|
if (t[0] == ARRAY_OPEN) {
|
||||||
|
SkipOverFirstChar(f, pos);
|
||||||
|
auto c = ParseArray(f, pos, 0);
|
||||||
|
if (PeekToken(f, pos)[0] != ARRAY_CLOSE)
|
||||||
|
throw std::runtime_error("Cannot match closing Array");
|
||||||
|
else
|
||||||
|
SkipOverFirstChar(f, pos);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else if (t[0] == GROUP_OPEN) {
|
||||||
|
SkipOverFirstChar(f, pos);
|
||||||
|
auto c = ParseCommand(f, pos);
|
||||||
|
if (PeekToken(f, pos)[0] != GROUP_CLOSE)
|
||||||
|
throw std::runtime_error("Cannot match closing subexpression");
|
||||||
|
else
|
||||||
|
SkipOverFirstChar(f, pos);
|
||||||
|
return Object(ParseType::Subexpression, c);
|
||||||
|
}
|
||||||
|
else if (t[0] == GROUP_CLOSE)
|
||||||
|
throw std::runtime_error("Cannot match closing subexpression, likely too few arguments");
|
||||||
|
else if (t[0] == QUOTE)
|
||||||
|
return { ParseType::String, ParseString(f, pos) };
|
||||||
|
else if (t[0] == ARRAY_CLOSE)
|
||||||
|
throw std::runtime_error("Cannot match closing array");
|
||||||
|
else {
|
||||||
|
auto token = GetToken(f, pos);
|
||||||
|
if (IsNumeric(token))
|
||||||
|
return { ParseType::Number, std::stof(token) };
|
||||||
|
else if (IsLegalSymbolName(token))
|
||||||
|
return { ParseType::Symbol, token };
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Illegal symbol");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Command ParseDialogue(const std::string& s) {
|
||||||
|
return { { ParseType::Symbol, "Say" }, { ParseType::String, s } };
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene ParseScene(const std::string& f, size_t& pos) {
|
||||||
SkipComments(f, pos);
|
SkipComments(f, pos);
|
||||||
|
|
||||||
if (!(GetToken(f, pos) == BEGIN.accept))
|
if (!(GetToken(f, pos) == BEGIN.accept))
|
||||||
throw std::runtime_error("Could not match accept at root");
|
throw std::runtime_error("Could not match accept at root");
|
||||||
|
|
||||||
auto scene_name = GetToken(f, pos);
|
auto scene_name = GetToken(f, pos);
|
||||||
if (!IsSymbol(scene_name)) throw std::runtime_error("Illegal Scene name");
|
if (!IsLegalSymbolName(scene_name)) throw std::runtime_error("Illegal Scene name");
|
||||||
Scene s{ scene_name };
|
Scene s{ scene_name };
|
||||||
|
|
||||||
state = ParseState::Command;
|
bool dialogue_mode = false;
|
||||||
|
|
||||||
while (PeekToken(f, pos) != END.accept) {
|
while (PeekToken(f, pos) != END.accept) {
|
||||||
ParseCommand(state, f, pos, s);
|
if (!dialogue_mode)
|
||||||
|
if (PeekToken(f, pos) == DIALOGUE_OPEN.accept) {
|
||||||
|
dialogue_mode = true;
|
||||||
|
GetToken(f, pos); // skip DIALOGUE_OPEN
|
||||||
|
SkipComments(f, pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s.append(ParseCommand(f, pos));
|
||||||
|
else {
|
||||||
|
auto end = f.find(NEWLINE.accept + DIALOGUE_CLOSE.accept, pos);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
throw std::runtime_error("Dialogue does not terminate");
|
||||||
|
auto lines = split_string_by_lines(f.substr(pos, end - pos));
|
||||||
|
for (auto& l : lines) {
|
||||||
|
s.append(ParseDialogue(l));
|
||||||
|
}
|
||||||
|
dialogue_mode = false;
|
||||||
|
pos = end;
|
||||||
|
GetToken(f, pos); // skip DIALOGUE_CLOSE
|
||||||
|
SkipComments(f, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dialogue_mode)
|
||||||
|
throw std::runtime_error("Illegal Scene end");
|
||||||
|
|
||||||
GetToken(f, pos); // skip END
|
GetToken(f, pos); // skip END
|
||||||
|
|
||||||
scenes.push_back(s);
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Scene EvalScene(const std::vector<std::vector<Parse>>& parses) { // TODO THIS IS TOTALLY FUCKED
|
/*Scene EvalScene(const std::vector<std::vector<Parse>>& parses) { // TODO THIS IS TOTALLY FUCKED
|
||||||
|
@ -352,11 +367,10 @@ namespace {
|
||||||
namespace NVL {
|
namespace NVL {
|
||||||
void ParseFile(const std::string& path) {
|
void ParseFile(const std::string& path) {
|
||||||
std::string f = read_file_to_string(path);
|
std::string f = read_file_to_string(path);
|
||||||
ParseState state = ParseState::Root;
|
|
||||||
|
|
||||||
std::vector<Scene> list {}; // Vector of scenes which each contain a vector of Parses
|
std::vector<Scene> list {}; // Vector of scenes which each contain a vector of Parses
|
||||||
for (size_t i = 0; i < f.length(); i++) {
|
for (size_t i = 0; i < f.length(); i++) {
|
||||||
ParseScene(state, f, i, list);
|
list.push_back(ParseScene(f, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -61,6 +61,6 @@ Choice var4 ["Apple", "Orange"]
|
||||||
// to have ways to terminate a scene other than END, for instance JUMP can be an alternative like this:
|
// to have ways to terminate a scene other than END, for instance JUMP can be an alternative like this:
|
||||||
// JUMP Scene2
|
// JUMP Scene2
|
||||||
// we can equally do something like this
|
// we can equally do something like this
|
||||||
// JUMP (switch var4 ("Apple" RouteA) ("Orange" RouteB) (default RouteC))
|
// JUMP (switch var4 [["Apple", RouteA], ["Orange", RouteB], [default, RouteC]])
|
||||||
|
|
||||||
END
|
END
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
BEGIN Scene1
|
BEGIN Scene1
|
||||||
hello "String \\ sdsd \" \\ \" sds"
|
hello "String \\ sdsd \" \\ \" sds" 873482384 .2342342
|
||||||
END
|
END
|
||||||
|
|
Loading…
Add table
Reference in a new issue