incomplete match

This commit is contained in:
lachrymaL 2021-12-13 14:04:12 -05:00
parent 13b14f4002
commit 87b9471735
No known key found for this signature in database
GPG key ID: F3640ACFA174B1C1
7 changed files with 94 additions and 23 deletions

View file

@ -1,13 +1,10 @@
#include "Parser.h" #include "Parser.h"
#include "Environment.h" #include "Environment.h"
#include <functional>
#include <any>
#include <string> #include <string>
#include <iostream> #include <iostream>
int main() { int main() {
auto f = [](NVL::Variable) { return NVL::Variable(NVL::Type::Nil); }; NVL::Variable v([](NVL::Variable) { return NVL::Variable(NVL::Type::Nil); }, 1);
NVL::Variable v(f, 1);
NVL::ENVIRONMENT.enter("hello", v); NVL::ENVIRONMENT.enter("hello", v);

View file

@ -26,7 +26,7 @@ namespace {
struct Match { struct Match {
std::string accept; std::string accept;
constexpr operator char() const { operator char() const {
return accept[0]; return accept[0];
} }
bool operator== (const std::string& other) const { bool operator== (const std::string& other) const {
@ -36,7 +36,7 @@ namespace {
const ParseGroup NUMERIC = { "1234567890" }; const ParseGroup NUMERIC = { "1234567890" };
const Match DECIMAL_DOT = { "." }; const Match DECIMAL_DOT = { "." };
const ParseGroup ALPHA = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst" }; const ParseGroup ALPHA = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" };
const Match ARRAY_OPEN = { "[" }; const Match ARRAY_OPEN = { "[" };
const Match ARRAY_CLOSE = { "]" }; const Match ARRAY_CLOSE = { "]" };
const Match ARRAY_DELIM = { "," }; const Match ARRAY_DELIM = { "," };
@ -60,24 +60,46 @@ namespace {
char(COMMENT_BEGIN) char(COMMENT_BEGIN)
}; };
const Match NEWLINE = { "\n" }; const Match NEWLINE = { "\n" };
const Match ESCAPE = { "\\" };
const ParseGroup ESCAPED = { "\\\"" }; const ParseGroup ESCAPED = { "\\\"" };
const Match ESCAPE = { "\\" };
// Dialogue mode matches
const Match MARKUP_OPEN = { "[" };
const Match MARKUP_CLOSE = { "]" };
const Match SPEAKER_OPEN = { "[" };
const Match SPEAKER_CLOSE = { "]" };
const Match MARKUP_TEXT_OPEN = { "{" };
const Match MARKUP_TEXT_CLOSE = { "}" };
const Match TEMPLATE_IND = { "$" };
const Match TEMPLATE_OPEN = { "{" };
const Match TEMPLATE_CLOSE = { "}" };
const Match COMMAND_ESCAPE = { "*!" };
const ParseGroup DIALOGUE_ESCAPED_SINGLE = {
ESCAPE.accept +
char(MARKUP_OPEN) +
char(MARKUP_CLOSE) +
char(MARKUP_TEXT_OPEN) +
char(MARKUP_TEXT_CLOSE) +
// char(SPEAKER_OPEN) +
// char(SPEAKER_CLOSE) +
char(TEMPLATE_IND)
// char(TEMPLATE_OPEN) +
// char(TEMPLATE_CLOSE)
};
enum class ParseType { Symbol, Number, String, Array, Subexpression }; 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);
{ // Some apps on Windows adds this signature in front of UTF-8 files when saving { // Some apps on Windows adds this signature in front of UTF-8 files when saving
char a, b, c; char a, b, c;
a = f.get(); a = f.get(); b = f.get(); c = f.get();
b = f.get(); if (a != (char)0xEF || b != (char)0xBB || c != (char)0xBF)
c = f.get();
if (a != (char)0xEF || b != (char)0xBB || c != (char)0xBF) {
f.seekg(0); f.seekg(0);
} else
else {
std::cerr << "Warning: Windows UTF-8 BOM skipped" << std::endl; std::cerr << "Warning: Windows UTF-8 BOM skipped" << std::endl;
}
} }
std::stringstream buffer; std::stringstream buffer;
buffer << f.rdbuf(); buffer << f.rdbuf();
@ -125,7 +147,6 @@ namespace {
}; };
using Command = std::vector<Object>; using Command = std::vector<Object>;
class Scene { class Scene {
std::string name; std::string name;
std::vector<Command> commands{}; std::vector<Command> commands{};
@ -136,6 +157,15 @@ namespace {
} }
}; };
struct Markup {
//... TODO
};
struct MarkupInstance {
std::pair<unsigned, unsigned> range;
std::string effect; //TEMP
};
void SkipWS(const std::string& f, size_t& pos) { void SkipWS(const std::string& f, size_t& pos) {
while (WS.accept.find(f[pos]) != std::string::npos) while (WS.accept.find(f[pos]) != std::string::npos)
pos++; pos++;
@ -292,7 +322,46 @@ namespace {
} }
Command ParseDialogue(const std::string& s) { Command ParseDialogue(const std::string& s) {
return { { ParseType::Symbol, "Say" }, { ParseType::String, s } }; if (s.substr(0, 2) == COMMAND_ESCAPE.accept) {
size_t dummy = 0;
return ParseCommand(s.substr(2), dummy); // TODO string[] will throw on this 100%, maybe do ParseDialogueCommand
}
if (s.back() == SPEAKER_CLOSE) {
if (s.front() == SPEAKER_OPEN) {
auto name = s.substr(1, s.length() - 2);
if (IsLegalSymbolName(name))
return { { ParseType::Symbol, "SwitchSpeaker" }, { ParseType::String, name } };
}
else
throw std::runtime_error("Malformed speaker command");
}
std::vector<int> discards;
for (int i = 0; i < s.length(); i++) {
if (s[i] == ESCAPE) {
if (DIALOGUE_ESCAPED_SINGLE.accept.find(s[i]) != std::string::npos) {
discards.push_back(i++);
}
else
throw std::runtime_error("Unrecognized escape sequence");
}
}
std::string new_s{s};
for (int i = 0; i < discards.size(); i++) {
new_s.erase(discards[i] - i, 1);
discards[i] -= i; // New indices become the positions of the escaped characters
}
// TODO
for (int i = 0; i < s.length(); i++) {
if (!discards.empty() && discards[0] < i) {
discards.erase(discards.begin());
}
}
std::cout << new_s << std::endl;
return { { ParseType::Symbol, "Say" }, { ParseType::String, new_s } };
} }
Scene ParseScene(const std::string& f, size_t& pos) { Scene ParseScene(const std::string& f, size_t& pos) {

View file

@ -26,7 +26,7 @@ Every new line is a new "click". I discarded the "pause" idea.
[Bailey] [Bailey]
Je ne suis plus Alex. Je ne suis plus Alex.
Ça ne me arrête pas de vous démontrer notre support multilingue noblement distingué. Ça ne m'arrête pas de vous démontrer notre support multilingue noblement distingué.
[Catherine] [Catherine]
CJKテスト CJKテスト
@ -44,7 +44,7 @@ To grab a value from the environment, do it like this: ${var}.
This is also the syntax to evaluate a command from dialogue mode. This is also the syntax to evaluate a command from dialogue mode.
If the return is void it will say "undefined" or something like that. If the return is void it will say "undefined" or something like that.
*! This "is a command in dialogue mode." *! This "is a command in dialogue mode." // Dialogue mode commands have to be one liners
*! Set var (+ var 1) *! Set var (+ var 1)
[NARRATION] [NARRATION]
@ -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 [[0, RouteA], [1, RouteB], [default, RouteC]])
END END

View file

@ -1,7 +1,12 @@
BEGIN Scene1 BEGIN Scene1
<<- <<-
[Alex]
Hello. Welcome to dialogue mode.
Every new line is a new "click". I discarded the "pause" idea.
[Bailey]
Je ne suis plus Alex. Je ne suis plus Alex.
Ça ne me arrête pas de vous démontrer notre support multilingue noblement distingué. Ça ne m'arrête pas de vous démontrer notre support multilingue noblement distingué.
[Catherine]
CJKテスト CJKテスト
夏はマシンガン。 夏はマシンガン。
->> ->>