comments and refactor
This commit is contained in:
parent
34c0fbf38a
commit
81ebf1d8eb
2 changed files with 95 additions and 79 deletions
147
NouVeL/NVL.cpp
147
NouVeL/NVL.cpp
|
@ -2,6 +2,11 @@
|
||||||
#include "NVL.h"
|
#include "NVL.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
void skip_ws(std::ifstream& stream)
|
||||||
|
{
|
||||||
|
stream >> std::ws;
|
||||||
|
}
|
||||||
|
|
||||||
const std::map<char, char> SCOPER_MAP = {
|
const std::map<char, char> SCOPER_MAP = {
|
||||||
{'{', '}' }, // CURLY
|
{'{', '}' }, // CURLY
|
||||||
{'<', '>'}, // ANGLED
|
{'<', '>'}, // ANGLED
|
||||||
|
@ -14,6 +19,7 @@ namespace {
|
||||||
|
|
||||||
bool need_escape(char c)
|
bool need_escape(char c)
|
||||||
{
|
{
|
||||||
|
// todo: refactor, too cryptic
|
||||||
return (c == '\'' || c == '\"');
|
return (c == '\'' || c == '\"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +29,10 @@ namespace {
|
||||||
|
|
||||||
std::streampos scope_cope(char scope_char, std::ifstream& stream)
|
std::streampos scope_cope(char scope_char, std::ifstream& stream)
|
||||||
{
|
{
|
||||||
|
// important
|
||||||
|
// scope_cope() expects the scope opener to already have been fetched and stored in scope_char
|
||||||
|
// i.o.w. it wont be able to cope properly because there will be one extra level of scope that it cannot match
|
||||||
|
|
||||||
std::streampos initial = stream.tellg();
|
std::streampos initial = stream.tellg();
|
||||||
|
|
||||||
std::streampos final;
|
std::streampos final;
|
||||||
|
@ -34,15 +44,10 @@ namespace {
|
||||||
while (!current_scope.Scope.empty()) {
|
while (!current_scope.Scope.empty()) {
|
||||||
stream.get(c);
|
stream.get(c);
|
||||||
|
|
||||||
bool no_more_nesting_quotes = false;
|
// there cannot be any more scope inside of quoted strings
|
||||||
for (auto& x : current_scope.Scope)
|
bool no_more_nesting_quotes = (current_scope.Scope.back() == '\'' || current_scope.Scope.back() == '\"');
|
||||||
{
|
|
||||||
if (x == '\'' || x == '\"')
|
|
||||||
{
|
|
||||||
no_more_nesting_quotes = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// push scope if opening scoper is found
|
||||||
bool set_scope_on_this_iter = false;
|
bool set_scope_on_this_iter = false;
|
||||||
if (!no_more_nesting_quotes) {
|
if (!no_more_nesting_quotes) {
|
||||||
for (auto const& x : SCOPER_MAP)
|
for (auto const& x : SCOPER_MAP)
|
||||||
|
@ -55,6 +60,8 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pop last scope if ending scoper is found
|
||||||
|
// set_scope_on_this_iter to prevent immediately popping scopers that have the same closers and openers
|
||||||
if (!set_scope_on_this_iter && c == SCOPER_MAP.at(current_scope.Scope.back()))
|
if (!set_scope_on_this_iter && c == SCOPER_MAP.at(current_scope.Scope.back()))
|
||||||
current_scope.Scope.pop_back();
|
current_scope.Scope.pop_back();
|
||||||
|
|
||||||
|
@ -67,6 +74,7 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cannot match all the copes and has read to the end of the file
|
||||||
if (stream.eof())
|
if (stream.eof())
|
||||||
{
|
{
|
||||||
std::cerr << "Can't cope with scope!" << std::endl;
|
std::cerr << "Can't cope with scope!" << std::endl;
|
||||||
|
@ -83,37 +91,46 @@ namespace {
|
||||||
|
|
||||||
std::string read_sequence_name(std::ifstream& nvl)
|
std::string read_sequence_name(std::ifstream& nvl)
|
||||||
{
|
{
|
||||||
nvl >> std::ws;
|
// this function will move the reading head of nvl, this is hard to keep track of but simplifies the program
|
||||||
|
skip_ws(nvl);
|
||||||
std::string token;
|
std::string token;
|
||||||
char c;
|
char c{};
|
||||||
while (nvl.get(c))
|
|
||||||
|
nvl.get(c);
|
||||||
|
while (c != ' ' && c != '{' && c != '\n')
|
||||||
{
|
{
|
||||||
if (c == ' ' || c == '{' || c == '\n')
|
|
||||||
{
|
|
||||||
nvl.putback(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
token += c;
|
token += c;
|
||||||
|
nvl.get(c);
|
||||||
}
|
}
|
||||||
|
nvl.putback(c);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skip_comment_ouside_sequence(std::ifstream& nvl, char& c)
|
void skip_comment_ouside_sequence(std::ifstream& nvl, char& c)
|
||||||
{
|
{
|
||||||
// assumes c is ';'
|
if (nvl.peek() == ';')
|
||||||
|
{
|
||||||
|
nvl.get(c);
|
||||||
while (c != '\n')
|
while (c != '\n')
|
||||||
{
|
{
|
||||||
nvl.get(c);
|
nvl.get(c);
|
||||||
}
|
}
|
||||||
nvl >> std::ws;
|
|
||||||
if (nvl.peek() == ';')
|
skip_ws(nvl);
|
||||||
{
|
|
||||||
nvl.get(c);
|
|
||||||
skip_comment_ouside_sequence(nvl, c);
|
skip_comment_ouside_sequence(nvl, c);
|
||||||
|
|
||||||
|
skip_ws(nvl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void indent_loop(int indent)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < indent; i++)
|
||||||
|
{
|
||||||
|
std::cout << "\t";
|
||||||
}
|
}
|
||||||
nvl >> std::ws;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,30 +143,32 @@ namespace NVL
|
||||||
Context this_context = parent_context;
|
Context this_context = parent_context;
|
||||||
this_context.Scope_Hierarchy.push_back(this_object);
|
this_context.Scope_Hierarchy.push_back(this_object);
|
||||||
|
|
||||||
nvl >> std::ws;
|
skip_ws(nvl);
|
||||||
|
|
||||||
std::streampos end; // unused if object is not scoped
|
std::streampos end; // unused if object is not scoped
|
||||||
bool is_comment = false;
|
|
||||||
|
|
||||||
std::variant<std::string, std::vector<Object>> content = "";
|
std::variant<std::string, std::vector<Object>> content = ""; // init to empty str
|
||||||
char c{};
|
char c{};
|
||||||
|
|
||||||
|
// early exit for comments
|
||||||
if (nvl.peek() == ';' && is_parent_call)
|
if (nvl.peek() == ';' && is_parent_call)
|
||||||
{
|
{
|
||||||
while (nvl.peek() != '\n')
|
while (nvl.peek() != '\n')
|
||||||
nvl.get(c);
|
nvl.get(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (nvl.peek())
|
switch (nvl.peek())
|
||||||
{
|
{
|
||||||
case '[': // List
|
case '[': // List
|
||||||
nvl.get(c); // do not exchange this line with the next one
|
nvl.get(c);
|
||||||
end = scope_cope('[', nvl);
|
end = scope_cope('[', nvl);
|
||||||
while (nvl.tellg() < end - static_cast<std::streampos>(1))
|
while (nvl.tellg() < end - static_cast<std::streampos>(1))
|
||||||
{
|
{
|
||||||
parse_Object<false, false>(this_context, nvl);
|
parse_Object<false, false>(this_context, nvl);
|
||||||
nvl >> std::ws;
|
skip_ws(nvl);
|
||||||
}
|
}
|
||||||
nvl.get(c);
|
nvl.get(c); // skip ending scoper (']')
|
||||||
break;
|
break;
|
||||||
case '<': // Dialogue, not yet implemented
|
case '<': // Dialogue, not yet implemented
|
||||||
end = scope_cope('<', nvl);
|
end = scope_cope('<', nvl);
|
||||||
|
@ -160,20 +179,27 @@ namespace NVL
|
||||||
while (nvl.tellg() < end - static_cast<std::streampos>(1))
|
while (nvl.tellg() < end - static_cast<std::streampos>(1))
|
||||||
{
|
{
|
||||||
nvl.get(c);
|
nvl.get(c);
|
||||||
|
|
||||||
|
// do not concat escaping '\' to content
|
||||||
if (c == '\\' && (nvl.peek() == '\'' || nvl.peek() == '\"'))
|
if (c == '\\' && (nvl.peek() == '\'' || nvl.peek() == '\"'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
content = std::get<std::string>(content) + c;
|
content = std::get<std::string>(content) + c;
|
||||||
}
|
}
|
||||||
nvl.get(c); // rid of final scoper
|
nvl.get(c); // skip ending scoper
|
||||||
|
|
||||||
this_object.Value = std::get<std::string>(content);
|
this_object.Value = std::get<std::string>(content);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
for (nvl.get(c); !(c == ' ' || c == '\n' || c == '}' || c == ']' || c == ','); nvl.get(c))
|
nvl.get(c);
|
||||||
|
while (c != ' ' && c != '\n' && c != '}' && c != ']' && c != ',')
|
||||||
{
|
{
|
||||||
content = std::get<std::string>(content) + c;
|
content = std::get<std::string>(content) + c;
|
||||||
|
nvl.get(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ']' handled in next object parse, '}' handled in sequence parse, '\n' will be skipped somewhere with skip_ws(), where? idk
|
||||||
if (c == ']' || c == '}' || c == '\n')
|
if (c == ']' || c == '}' || c == '\n')
|
||||||
{
|
{
|
||||||
nvl.putback(c);
|
nvl.putback(c);
|
||||||
|
@ -182,6 +208,7 @@ namespace NVL
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// try number
|
||||||
this_object.Value = std::stof(std::get<std::string>(content));
|
this_object.Value = std::stof(std::get<std::string>(content));
|
||||||
}
|
}
|
||||||
catch (std::exception)
|
catch (std::exception)
|
||||||
|
@ -195,6 +222,10 @@ namespace NVL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// early return if string is empty, this should only happen if calling from an object (not a call)
|
||||||
|
if (std::all_of(std::get<std::string>(content).begin(), std::get<std::string>(content).end(), isspace))
|
||||||
|
return;
|
||||||
|
// default case if content does not match keywords
|
||||||
this_object.Value = std::get<std::string>(content);
|
this_object.Value = std::get<std::string>(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,15 +237,11 @@ namespace NVL
|
||||||
|
|
||||||
if (is_parent_call)
|
if (is_parent_call)
|
||||||
(std::get<std::reference_wrapper<Call>>(parent_context.Scope_Hierarchy.back())).get().Objects.push_back(this_object);
|
(std::get<std::reference_wrapper<Call>>(parent_context.Scope_Hierarchy.back())).get().Objects.push_back(this_object);
|
||||||
else if ((std::get<std::reference_wrapper<Object>>(parent_context.Scope_Hierarchy.back())).get().Value.index() == 4) // 4 for list
|
else if ((std::get<std::reference_wrapper<Object>>(parent_context.Scope_Hierarchy.back())).get().Value.index() == 4) // 4 for list, indicates that parent is an object that is already a vector of objects
|
||||||
{
|
|
||||||
std::get<std::vector<Object>>((std::get<std::reference_wrapper<Object>>(parent_context.Scope_Hierarchy.back())).get().Value).push_back(this_object);
|
std::get<std::vector<Object>>((std::get<std::reference_wrapper<Object>>(parent_context.Scope_Hierarchy.back())).get().Value).push_back(this_object);
|
||||||
}
|
else // parent is not yet vector, initialize as (change from nil to) vector
|
||||||
else
|
|
||||||
{
|
|
||||||
(std::get<std::reference_wrapper<Object>>(parent_context.Scope_Hierarchy.back())).get().Value = std::vector<Object> { this_object };
|
(std::get<std::reference_wrapper<Object>>(parent_context.Scope_Hierarchy.back())).get().Value = std::vector<Object> { this_object };
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void parse_Call(Context parent_context, std::ifstream& nvl)
|
void parse_Call(Context parent_context, std::ifstream& nvl)
|
||||||
{
|
{
|
||||||
|
@ -223,8 +250,10 @@ namespace NVL
|
||||||
Context this_context = parent_context;
|
Context this_context = parent_context;
|
||||||
this_context.Scope_Hierarchy.push_back(this_call);
|
this_context.Scope_Hierarchy.push_back(this_call);
|
||||||
|
|
||||||
|
// parse the symbol (first obj in call)
|
||||||
parse_Object<true, true>(this_context, nvl);
|
parse_Object<true, true>(this_context, nvl);
|
||||||
|
|
||||||
|
// parse the rest
|
||||||
while (!(nvl.peek() == '\n' || nvl.peek() == '}'))
|
while (!(nvl.peek() == '\n' || nvl.peek() == '}'))
|
||||||
{
|
{
|
||||||
parse_Object<true, false>(this_context, nvl);
|
parse_Object<true, false>(this_context, nvl);
|
||||||
|
@ -239,19 +268,15 @@ namespace NVL
|
||||||
Context this_context = parent_context;
|
Context this_context = parent_context;
|
||||||
this_context.Scope_Hierarchy.push_back(this_sequence);
|
this_context.Scope_Hierarchy.push_back(this_sequence);
|
||||||
|
|
||||||
nvl >> std::ws;
|
skip_ws(nvl);
|
||||||
|
|
||||||
char c{};
|
char c{};
|
||||||
|
|
||||||
if (nvl.peek() == ';')
|
|
||||||
{
|
|
||||||
nvl.get(c);
|
|
||||||
skip_comment_ouside_sequence(nvl, c);
|
skip_comment_ouside_sequence(nvl, c);
|
||||||
}
|
|
||||||
|
|
||||||
this_sequence = Sequence(read_sequence_name(nvl));
|
this_sequence = Sequence(read_sequence_name(nvl));
|
||||||
|
|
||||||
nvl >> std::ws;
|
skip_ws(nvl);
|
||||||
|
|
||||||
nvl.get(c); // get {
|
nvl.get(c); // get {
|
||||||
|
|
||||||
if (c != '{')
|
if (c != '{')
|
||||||
|
@ -265,7 +290,7 @@ namespace NVL
|
||||||
while (nvl.tellg() < end_pos - static_cast<std::streampos>(1))
|
while (nvl.tellg() < end_pos - static_cast<std::streampos>(1))
|
||||||
{
|
{
|
||||||
parse_Call(this_context, nvl);
|
parse_Call(this_context, nvl);
|
||||||
nvl >> std::ws;
|
skip_ws(nvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
nvl.get(c); // get }
|
nvl.get(c); // get }
|
||||||
|
@ -279,22 +304,18 @@ namespace NVL
|
||||||
nvl.open(path);
|
nvl.open(path);
|
||||||
|
|
||||||
if (nvl.is_open()) {
|
if (nvl.is_open()) {
|
||||||
|
|
||||||
Context current_context;
|
Context current_context;
|
||||||
|
|
||||||
current_context.Scope_Hierarchy.push_back(root);
|
current_context.Scope_Hierarchy.push_back(root);
|
||||||
|
|
||||||
while (!nvl.eof()) {
|
while (!nvl.eof()) {
|
||||||
|
// parse_Sequence() already takes care of comments before a sequence
|
||||||
parse_Sequence(current_context, nvl);
|
parse_Sequence(current_context, nvl);
|
||||||
nvl >> std::ws;
|
skip_ws(nvl);
|
||||||
{
|
|
||||||
if (nvl.peek() == ';') {
|
|
||||||
char c{};
|
char c{};
|
||||||
nvl.get(c);
|
|
||||||
skip_comment_ouside_sequence(nvl, c);
|
skip_comment_ouside_sequence(nvl, c);
|
||||||
}
|
|
||||||
}
|
skip_ws(nvl);
|
||||||
nvl >> std::ws;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nvl.close();
|
nvl.close();
|
||||||
|
@ -306,18 +327,12 @@ namespace NVL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void indent_loop(int indent)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < indent; i++)
|
|
||||||
{
|
|
||||||
std::cout << "\t";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Object::Print(int indent)
|
void Object::Print(int indent)
|
||||||
{
|
{
|
||||||
indent_loop(indent);
|
indent_loop(indent);
|
||||||
std::cout << "Object: ";
|
std::cout << "Object: ";
|
||||||
|
|
||||||
switch (Value.index())
|
switch (Value.index())
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -337,6 +352,7 @@ namespace NVL
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
std::cout << "List:" << std::endl;
|
std::cout << "List:" << std::endl;
|
||||||
|
|
||||||
for (auto& x : std::get<std::vector<Object>>(Value))
|
for (auto& x : std::get<std::vector<Object>>(Value))
|
||||||
{
|
{
|
||||||
x.Print(indent + 1);
|
x.Print(indent + 1);
|
||||||
|
@ -344,30 +360,37 @@ namespace NVL
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Call::Print(int indent)
|
void Call::Print(int indent)
|
||||||
{
|
{
|
||||||
indent_loop(indent);
|
indent_loop(indent);
|
||||||
std::cout << "Call:" << std::endl;
|
std::cout << "Call:" << std::endl;
|
||||||
|
|
||||||
for (auto& x : Objects)
|
for (auto& x : Objects)
|
||||||
{
|
{
|
||||||
x.Print(indent + 1);
|
x.Print(indent + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequence::Print(int indent)
|
void Sequence::Print(int indent)
|
||||||
{
|
{
|
||||||
indent_loop(indent);
|
indent_loop(indent);
|
||||||
std::cout << "Sequence " << Name << ":" << std::endl;
|
std::cout << "Sequence " << Name << ":" << std::endl;
|
||||||
|
|
||||||
for (auto& x : Calls)
|
for (auto& x : Calls)
|
||||||
{
|
{
|
||||||
x.Print(indent + 1);
|
x.Print(indent + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
indent_loop(indent);
|
indent_loop(indent);
|
||||||
std::cout << "------------------------" << std::endl;
|
std::cout << "-----------------------------------------------" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::Print(int indent)
|
void Tree::Print(int indent)
|
||||||
{
|
{
|
||||||
indent_loop(indent);
|
indent_loop(indent);
|
||||||
std::cout << "Tree:" << std::endl;
|
std::cout << "Tree:" << std::endl;
|
||||||
|
|
||||||
for (auto& x : Sequences)
|
for (auto& x : Sequences)
|
||||||
{
|
{
|
||||||
x.Print(indent + 1);
|
x.Print(indent + 1);
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <regex>
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
namespace NVL
|
namespace NVL
|
||||||
|
@ -65,11 +65,4 @@ namespace NVL
|
||||||
};
|
};
|
||||||
|
|
||||||
void parse_NVL(Tree& root, std::string path);
|
void parse_NVL(Tree& root, std::string path);
|
||||||
|
|
||||||
void parse_Sequence(Context parent_context, std::ifstream& nvl);
|
|
||||||
|
|
||||||
void parse_Call(Context parent_context, std::ifstream& nvl);
|
|
||||||
|
|
||||||
template <bool is_parent_call, bool is_symbol>
|
|
||||||
void parse_Object(Context parent_context, std::ifstream& nvl);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue