comments and refactor

This commit is contained in:
lachrymaL 2021-05-15 17:48:37 -04:00
parent 34c0fbf38a
commit 81ebf1d8eb
No known key found for this signature in database
GPG key ID: F3640ACFA174B1C1
2 changed files with 95 additions and 79 deletions

View file

@ -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 == '\"');
} }
@ -21,8 +27,12 @@ namespace {
std::vector<char> Scope; std::vector<char> Scope;
}; };
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') token += c;
{ nvl.get(c);
nvl.putback(c);
break;
}
else
token += 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 ';'
while (c != '\n')
{
nvl.get(c);
}
nvl >> std::ws;
if (nvl.peek() == ';') if (nvl.peek() == ';')
{ {
nvl.get(c); nvl.get(c);
while (c != '\n')
{
nvl.get(c);
}
skip_ws(nvl);
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,21 +179,28 @@ 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);
if (c == '\\' && (nvl.peek() == '\'' || nvl.peek() == '\"'))
// do not concat escaping '\' to content
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);
} }
if (c == ']' || c == '}' || c == '\n')
// ']' handled in next object parse, '}' handled in sequence parse, '\n' will be skipped somewhere with skip_ws(), where? idk
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,14 +237,10 @@ 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{};
skip_comment_ouside_sequence(nvl, c);
if (nvl.peek() == ';')
{
nvl.get(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{}; skip_comment_ouside_sequence(nvl, c);
nvl.get(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);

View file

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