Heavily modify Target.hpp, add a pointerAs function, and add an overload to Yerbacon::exit
This commit is contained in:
parent
4771aed6b4
commit
c123965098
|
@ -47,6 +47,7 @@ namespace Yerbacon {
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
inline void exit(const char* reason) { exit({reason}); }
|
||||||
class Exception: public std::exception {
|
class Exception: public std::exception {
|
||||||
std::string exceptionCause;
|
std::string exceptionCause;
|
||||||
public:
|
public:
|
||||||
|
@ -60,6 +61,10 @@ namespace Yerbacon {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
template<typename T, typename U>
|
||||||
|
constexpr T& pointerAs(const std::unique_ptr<U>& ptr) { return reinterpret_cast<T&>(*ptr); }
|
||||||
|
|
||||||
#undef YBCON_VERSION
|
#undef YBCON_VERSION
|
||||||
#undef YBCON_FLAGS
|
#undef YBCON_FLAGS
|
||||||
#undef YBCON_COMPILER
|
#undef YBCON_COMPILER
|
||||||
|
|
|
@ -89,6 +89,7 @@ public:
|
||||||
}
|
}
|
||||||
return optional<reference_wrapper<T>>();
|
return optional<reference_wrapper<T>>();
|
||||||
};
|
};
|
||||||
|
inline decltype(*subComponents.data()) operator[](const unsigned int& index) const { return subComponents[index]; }
|
||||||
IS(StandardComponents::NamedIdentifier)
|
IS(StandardComponents::NamedIdentifier)
|
||||||
inline auto operator[](const string& key) const { return findReferenceByName<T>(key); }
|
inline auto operator[](const string& key) const { return findReferenceByName<T>(key); }
|
||||||
inline size_t getCompCount() const { return subComponents.size(); }
|
inline size_t getCompCount() const { return subComponents.size(); }
|
||||||
|
|
|
@ -7,18 +7,18 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <typeindex>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "../parsing/ParseComponents.hpp"
|
#include "../parsing/ParseComponents.hpp"
|
||||||
|
|
||||||
#define INCLUDECOMPONENT(X) virtual void on(const X& parseComponent) {}
|
|
||||||
class Target {
|
class Target {
|
||||||
constexpr static const char* const interpolationString = "${";
|
constexpr static const char* const interpolationString = "${";
|
||||||
constexpr static const char* const interpolationCloseString = "}";
|
constexpr static const char* const interpolationCloseString = "}";
|
||||||
protected:
|
protected:
|
||||||
virtual constexpr bool supportsOneLine() { return true; };
|
virtual constexpr bool supportsOneLine() { return true; };
|
||||||
std::stringstream output;
|
std::stringstream output;
|
||||||
INCLUDECOMPONENT(StandardComponents::Define);
|
|
||||||
INCLUDECOMPONENT(StandardComponents::types::String);
|
|
||||||
inline void stringInterpolation(const char* multiline, const string& view) { stringInterpolation(view, multiline, multiline); }
|
inline void stringInterpolation(const char* multiline, const string& view) { stringInterpolation(view, multiline, multiline); }
|
||||||
void stringInterpolation(string view, const char* openMultiline = "", const char* closeMultiline = "", const char* concatenationCharacters = "+") {
|
void stringInterpolation(string view, const char* openMultiline = "", const char* closeMultiline = "", const char* concatenationCharacters = "+") {
|
||||||
typedef string::size_type strSize;
|
typedef string::size_type strSize;
|
||||||
|
@ -62,33 +62,38 @@ protected:
|
||||||
}
|
}
|
||||||
} else output << openCharacters << view << closeCharacters << '\n';
|
} else output << openCharacters << view << closeCharacters << '\n';
|
||||||
}
|
}
|
||||||
INCLUDECOMPONENT(StandardComponents::Reference);
|
typedef function<void (const ParseTree& parsedTree, unsigned int& index)> task;
|
||||||
INCLUDECOMPONENT(StandardComponents::Class);
|
#define make_task(X, L) make_pair(type_index(typeid(X)), [this](const ParseTree& parsedTree, unsigned int& index) { const X& parseComponent = pointerAs<X>(parsedTree[index]); L })
|
||||||
|
typedef unordered_map<type_index, optional<task>> unordered_task_map;
|
||||||
|
virtual unordered_task_map getTaskMap() = 0;
|
||||||
public:
|
public:
|
||||||
|
unordered_task_map& getTaskMapInstance() {
|
||||||
|
static unordered_task_map staticMap = getTaskMap();
|
||||||
|
return staticMap;
|
||||||
|
};
|
||||||
static shared_ptr<Target> forName(string_view name, bool newLines);
|
static shared_ptr<Target> forName(string_view name, bool newLines);
|
||||||
|
const bool newLines;
|
||||||
#define with(X) if (id == typeid(X)) { this->on(reinterpret_cast<X&>(*component)); continue; }
|
|
||||||
string transpileWithTree(const ParseTree& tree) {
|
string transpileWithTree(const ParseTree& tree) {
|
||||||
|
const unordered_task_map& taskMap = getTaskMapInstance();
|
||||||
|
if (not newLines && !supportsOneLine()) {
|
||||||
|
throw Yerbacon::Exception("--newlines=off is not supported by the current target");
|
||||||
|
}
|
||||||
output.str(string());
|
output.str(string());
|
||||||
for (const unique_ptr<ParseComponent>& component: tree) {
|
for (unsigned int i = 0; i < tree.getCompCount(); ++i) {
|
||||||
|
const unique_ptr<ParseComponent>& component = tree[i];
|
||||||
const type_info& id = component->getId();
|
const type_info& id = component->getId();
|
||||||
with(StandardComponents::Define);
|
try {
|
||||||
with(StandardComponents::types::String);
|
const optional<task>& currentTask = taskMap.at(id);
|
||||||
with(StandardComponents::Reference);
|
if (currentTask.has_value()) currentTask.value()(tree, i);
|
||||||
with(StandardComponents::Class);
|
} catch (const out_of_range&) {
|
||||||
|
throw Yerbacon::Exception(string(id.name()) += " is not supported by the current target");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output.str();
|
return output.str();
|
||||||
};
|
};
|
||||||
#undef with
|
|
||||||
const bool newLines;
|
|
||||||
explicit Target(const bool newLines): newLines(newLines) {};
|
explicit Target(const bool newLines): newLines(newLines) {};
|
||||||
virtual ~Target() = default;
|
virtual ~Target() = default;
|
||||||
};
|
};
|
||||||
#undef INCLUDECOMPONENT
|
|
||||||
|
|
||||||
inline string transpile(const ParseTree& tree, const string_view& language, const bool newLines) {
|
|
||||||
return Target::forName(language, newLines)->transpileWithTree(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "implementations/Lua.hpp"
|
#include "implementations/Lua.hpp"
|
||||||
#include "implementations/Js.hpp"
|
#include "implementations/Js.hpp"
|
||||||
|
@ -121,10 +126,7 @@ shared_ptr<Target> Target::forName(string_view name, const bool newLines = true)
|
||||||
default: Yerbacon::exit({"\"", string(1, (char) toupper(name.at(1))).data(), name.substr(2).data(), "\" is not a valid target."});
|
default: Yerbacon::exit({"\"", string(1, (char) toupper(name.at(1))).data(), name.substr(2).data(), "\" is not a valid target."});
|
||||||
}
|
}
|
||||||
#undef ADDTARGET
|
#undef ADDTARGET
|
||||||
if (not newLines and not target->supportsOneLine()) {
|
#undef make_task
|
||||||
name.remove_prefix(1);
|
|
||||||
throw Yerbacon::Exception(string("--newlinesoff cannot be used with --target=") += name);
|
|
||||||
}
|
|
||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
#ifndef JS_HPP
|
#ifndef JS_HPP
|
||||||
#define JS_HPP JsTarget
|
#define JS_HPP JsTarget
|
||||||
|
using namespace StandardComponents;
|
||||||
|
|
||||||
struct JsTarget: Target {
|
struct JsTarget: Target {
|
||||||
void on(const StandardComponents::Define& parseComponent) override {
|
unordered_task_map getTaskMap() final {
|
||||||
output << (parseComponent.final ? "const " : "let ") << parseComponent.name << " = ";
|
return {
|
||||||
}
|
make_task(Define,
|
||||||
void on(const StandardComponents::types::String& parseComponent) override {
|
output << (parseComponent.final ? "const " : "let ") << parseComponent.name << " = ";
|
||||||
stringInterpolation(parseComponent.content);
|
output << "ah";
|
||||||
|
),
|
||||||
|
make_task(types::String, stringInterpolation(parseComponent.content);)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
using Target::Target;
|
using Target::Target;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
#ifndef LUA_HPP
|
#ifndef LUA_HPP
|
||||||
#define LUA_HPP LuaTarget
|
#define LUA_HPP LuaTarget
|
||||||
|
using namespace StandardComponents;
|
||||||
|
|
||||||
struct LuaTarget: Target {
|
struct LuaTarget: Target {
|
||||||
void on(const StandardComponents::Define& parseComponent) override {
|
unordered_task_map getTaskMap() final {
|
||||||
if (parseComponent.final) output << "local ";
|
return {
|
||||||
output << parseComponent.name;
|
make_task(Define,
|
||||||
if (parseComponent.final) output << " <const>"; // TODO Find an alternative to <const> for lua <5.4
|
if (parseComponent.final) output << "local ";
|
||||||
output << " = ";
|
output << parseComponent.name;
|
||||||
}
|
if (parseComponent.final) output << " <const>"; // TODO Find an alternative to <const> for lua <5.4
|
||||||
void on(const StandardComponents::types::String& parseComponent) override {
|
output << " = ";
|
||||||
stringInterpolation(parseComponent.content, "[[", "]]", "..");
|
),
|
||||||
|
make_task(types::String, stringInterpolation(parseComponent.content, "[[", "]]", "..");)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
using Target::Target;
|
using Target::Target;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
#ifndef PY_HPP
|
#ifndef PY_HPP
|
||||||
#define PY_HPP PyTarget
|
#define PY_HPP PyTarget
|
||||||
|
using namespace StandardComponents;
|
||||||
|
|
||||||
struct PyTarget: Target {
|
struct PyTarget: Target {
|
||||||
bool supportsOneLine() final { return false; }
|
bool supportsOneLine() final { return false; }
|
||||||
void on(const StandardComponents::Define& parseComponent) override {
|
unordered_task_map getTaskMap() final {
|
||||||
output << parseComponent.name << " = ";
|
return {
|
||||||
}
|
make_task(Define, output << parseComponent.name << " = ";),
|
||||||
void on(const StandardComponents::types::String& parseComponent) override {
|
make_task(types::String, stringInterpolation(R"(""")", parseComponent.content);)
|
||||||
stringInterpolation(R"(""")", parseComponent.content);
|
};
|
||||||
}
|
}
|
||||||
using Target::Target;
|
using Target::Target;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@ int main(int argc, char* argv[]) {
|
||||||
else if (currentArg == ArgumentAssignable("target")) {
|
else if (currentArg == ArgumentAssignable("target")) {
|
||||||
const string_view value = ArgumentAssignable::getValueFor(currentArg);
|
const string_view value = ArgumentAssignable::getValueFor(currentArg);
|
||||||
if (not value.empty()) (target = '.') += value;
|
if (not value.empty()) (target = '.') += value;
|
||||||
else Yerbacon::exit({"No target was provided."});
|
else Yerbacon::exit("No target was provided.");
|
||||||
}
|
}
|
||||||
else if (currentArg == Argument("parallel")) parallel = true;
|
else if (currentArg == Argument("parallel")) parallel = true;
|
||||||
else if (currentArg == ArgumentAssignable("newlines")) {
|
else if (currentArg == ArgumentAssignable("newlines")) {
|
||||||
|
@ -45,8 +45,9 @@ int main(int argc, char* argv[]) {
|
||||||
} else invalid_argument: Yerbacon::exit({"\"", currentArg.data(), "\" is not a valid argument."});
|
} else invalid_argument: Yerbacon::exit({"\"", currentArg.data(), "\" is not a valid argument."});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto compile = [&target, &newLines](string_view name) -> string {
|
const auto currentTarget = Target::forName(target, newLines);
|
||||||
string transpiledString = transpile(parseString(getFileContent(name.data())), target, newLines);
|
const auto compile = [&target, ¤tTarget](string_view name) -> string {
|
||||||
|
string transpiledString = currentTarget->transpileWithTree(parseString(getFileContent(name.data())));
|
||||||
name.remove_suffix(6);
|
name.remove_suffix(6);
|
||||||
string outputFile;
|
string outputFile;
|
||||||
(outputFile = name).append(target);
|
(outputFile = name).append(target);
|
||||||
|
|
Loading…
Reference in New Issue