diff --git a/CMakeLists.txt b/CMakeLists.txt index 94c1b9e..6b8b5a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,10 @@ # and include sub-projects here. # cmake_minimum_required (VERSION 3.8) + set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) project ("NouVeL") diff --git a/NouVeL/NVL.cpp b/NouVeL/NVL.cpp index 13e48a0..e7525bb 100644 --- a/NouVeL/NVL.cpp +++ b/NouVeL/NVL.cpp @@ -1,38 +1,230 @@ +#include #include "NVL.h" +namespace { + const std::map SCOPER_MAP = { + {'{', '}' }, // CURLY + {'<', '>'}, // ANGLED + {'(', ')'}, // BRACKET + {'[', ']'}, // SQUARE + + {'\'', '\''}, // SQUOTE + {'\"', '\"'} // DQUOTE + + }; + + bool need_escape(char c) + { + return (c == '\'' || c == '\"'); + } + + struct ScopeContext { + std::vector Scope; + }; + + std::streampos scope_cope(char scope_char, std::ifstream& stream) + { + std::streampos initial = stream.tellg(); + + std::streampos final; + char c{}; + + ScopeContext current_scope; + current_scope.Scope.push_back(scope_char); + + while (!current_scope.Scope.empty()) { + stream.get(c); + for (auto const& x : SCOPER_MAP) + { + if (c == x.first) { + current_scope.Scope.push_back(c); + break; + } + } + + if (c == '\\') // encounters an escaped sequence + { + char cc = stream.peek(); + if (need_escape(cc)) // see if the escaped char happens to be a scoper + { + stream.get(c); // skip it, since whoever wrote the script escaped it + } + } + + if (c == SCOPER_MAP.at(current_scope.Scope.back())) + current_scope.Scope.pop_back(); + + if (stream.eof()) + { + std::cerr << "Can't cope with scope!" << std::endl; + throw; + } + } + + stream.putback(c); + + final = stream.tellg(); + stream.seekg(initial); + + return final; + } + + std::string read_token(std::ifstream& nvl) + { + nvl >> std::ws; + std::string token; + char c; + while (nvl.get(c)) + { + if (c == ' ' || c == '{') + { + nvl.putback(c); + break; + } + else + token += c; + } + + return token; + } +} + namespace NVL { - void preprocess_subblocks(std::string calls) + void parse_Call(Context context, std::ifstream& nvl, std::streampos end_pos) { + Call this_call; + // temp fuckery + Object tmp_obj; + tmp_obj.Value; + + std::string tmp_str; + char c{}; + while (nvl.tellg() < end_pos) + { + nvl.get(c); + tmp_str += c; + } + + tmp_obj.Value = tmp_str; + + this_call.Objects.push_back(tmp_obj); + + std::get>(context.Scope_Hierarchy.back())->Calls.push_back(this_call); } - void collapse_Call(Call& call, std::string nvl) + void parse_Sequence(Context parent_context, std::ifstream& nvl) { + Sequence this_sequence = Sequence( read_token(nvl) ); + Context this_context = parent_context; + this_context.Scope_Hierarchy.push_back(std::make_shared(this_sequence)); + nvl >> std::ws; + + char c; + nvl.get(c); + if (c != '{') { + std::cerr << "Sequence parse failed!" << std::endl; + throw; + } + + std::streampos end_pos = scope_cope(c, nvl); + + while (nvl.tellg() < end_pos) + { + parse_Call(this_context, nvl, end_pos); + } + + std::get>(parent_context.Scope_Hierarchy.back())->Sequences.push_back(this_sequence); } - void parse_Sequence(Tree& root, std::string nvl) - { - - } - - int parse_NVL(Tree& root, std::string path) + void parse_NVL(Tree& root, std::string path) { std::ifstream nvl; nvl.open(path); if (nvl.is_open()) { - std::string out = std::string(std::istreambuf_iterator(nvl), std::istreambuf_iterator()); + Context current_context; - parse_Sequence(root, out); + current_context.Scope_Hierarchy.push_back(std::make_shared(root)); + + //while (!nvl.eof()) + parse_Sequence(current_context, nvl); nvl.close(); - return 0; } else { std::cerr << "Unable to read file " << path << std::endl; - return 1; + throw; + } + + } + + + void indent_loop(int indent) + { + for (int i = 0; i < indent; i++) + { + std::cout << "\t"; + } + } + void Token::Print() + { + std::cout << "Token: " << Identifier << std::endl; + } + void Object::Print(int indent) + { + indent_loop(indent); + std::cout << "Object: "; + switch (Value.index()) + { + case 0: + std::get(Value).Print(); + break; + case 1: + std::cout << "float: " << std::get(Value) << std::endl; + break; + case 2: + std::cout << "string: " << std::get(Value) << std::endl; + break; + case 3: + std::cout << "bool: " << std::get(Value) << std::endl; + break; + case 4: + std::cout << "List:" << std::endl; + for (auto& x : std::get>(Value)) + { + x.Print(indent + 1); + } + break; + } + } + void Call::Print(int indent) + { + indent_loop(indent); + std::cout << "Call:" << std::endl; + for (auto& x : Objects) + { + x.Print(indent + 1); + } + } + void Sequence::Print(int indent) + { + indent_loop(indent); + std::cout << "Sequence " << Name << ":" << std::endl; + for (auto& x : Calls) + { + x.Print(indent + 1); + } + } + void Tree::Print(int indent) + { + indent_loop(indent); + std::cout << "Tree:" << std::endl; + for (auto& x : Sequences) + { + x.Print(indent + 1); } } } \ No newline at end of file diff --git a/NouVeL/NVL.h b/NouVeL/NVL.h index ddc10c8..ff3afb7 100644 --- a/NouVeL/NVL.h +++ b/NouVeL/NVL.h @@ -6,49 +6,66 @@ #include #include #include -#include -#include + namespace NVL { - struct Symbol + struct Token { std::string Identifier; + + void Print(); }; struct Object { std::variant< - Symbol, + Token, float, std::string, bool, - std::vector + std::vector // Implies Object can be an array of other Object > Value; + + void Print(int indent); + }; struct Call { std::vector Objects; + void Print(int indent); }; struct Sequence { std::string Name; std::vector Calls; + + Sequence(std::string n) : Name(n) + {} + + void Print(int indent); }; struct Tree { std::vector Sequences; - void Print_Tree(int indent); + void Print(int indent); }; - int parse_NVL(Tree& root, std::string path); + struct Context { + std::vector, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr + >> Scope_Hierarchy; + }; - void parse_Sequence(Tree& root, std::string nvl); + void parse_NVL(Tree& root, std::string path); - void preprocess_subblocks(std::string calls); + void parse_Sequence(Context context, std::ifstream& nvl); - void collapse_Call(Call& call, std::string nvl); + void parse_Call(Context context, std::ifstream& nvl, std::streampos end_pos); } \ No newline at end of file diff --git a/NouVeL/NouVeL.cpp b/NouVeL/NouVeL.cpp index a2dcbb6..d9c627f 100644 --- a/NouVeL/NouVeL.cpp +++ b/NouVeL/NouVeL.cpp @@ -5,10 +5,9 @@ int main() const std::string PJ_DIR = "E:\\Archive\\Projects\\NouVeL\\"; NVL::Tree tree; - if (NVL::parse_NVL(tree, PJ_DIR + "myfile.txt")) - return 1; + NVL::parse_NVL(tree, PJ_DIR + "myfile.txt"); - tree.Print_Tree(0); + tree.Print(0); return 0; } diff --git a/myfile.txt b/myfile.txt index 9010119..0ca1e33 100644 --- a/myfile.txt +++ b/myfile.txt @@ -1,8 +1,6 @@ -asdasda sdsd -asdaskmds -ada -da -ds -sad -a -fagjkdlfngioesjf +dsahd { + dasjkhdakjsdasddsmnfdsf + asdkashjdsad + asdasdfdoy893eryh + :awesome: +}