Compare commits
3 Commits
d4df3aa4ea
...
dbb08a5299
Author | SHA1 | Date |
---|---|---|
Username404-59 | dbb08a5299 | |
Username404-59 | 2c0cec16d6 | |
Username404-59 | 7fb9ca37a7 |
|
@ -4,9 +4,13 @@
|
||||||
#include "parsing/ParseComponents.hpp"
|
#include "parsing/ParseComponents.hpp"
|
||||||
#include "Tasking.hpp"
|
#include "Tasking.hpp"
|
||||||
|
|
||||||
#define make_task(T, C, F) make_task_base_R(T, C, F)
|
using namespace StandardComponents;
|
||||||
|
|
||||||
struct SemanticAnalyser final: public Tasking {
|
struct SemanticAnalyser final: public Tasking {
|
||||||
|
typedef Yerbacon::Exception SemanticException;
|
||||||
|
static void error(const string_view& text, unsigned long line = 0) {
|
||||||
|
throw SemanticException(text, line);
|
||||||
|
}
|
||||||
const auto& analyseTree(const ParseTree& tree) {
|
const auto& analyseTree(const ParseTree& tree) {
|
||||||
const auto& task_map = getTaskMapInstance();
|
const auto& task_map = getTaskMapInstance();
|
||||||
for (unsigned int i = 0; i < tree.size(); ++i) {
|
for (unsigned int i = 0; i < tree.size(); ++i) {
|
||||||
|
@ -17,13 +21,23 @@ struct SemanticAnalyser final: public Tasking {
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
unordered_task_map getTaskMapInstance() final {
|
unordered_task_map getTaskMapInstance() final { // TODO Include line in error messages
|
||||||
|
using namespace StandardComponents;
|
||||||
return {
|
return {
|
||||||
|
make_nonlocal_task(Reference,
|
||||||
|
if (index > 0 and any_of(parsedTree.cbegin(), parsedTree.cbegin() + index + 1, [&parseComponent](const component_ptr& pointer){
|
||||||
|
try {
|
||||||
|
return dynamic_cast<NamedIdentifier<true>&>(*pointer).name == parseComponent.name;
|
||||||
|
} catch (const bad_cast&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})) { error(parseComponent.name + " has already been defined previously"); }
|
||||||
|
),
|
||||||
|
share_task(Reference, Function),
|
||||||
|
share_task(Reference, Class),
|
||||||
|
share_task(Reference, Define<true>),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef make_task
|
|
||||||
|
|
||||||
#endif //YERBACON_SEMANTICANALYSIS_HPP
|
#endif //YERBACON_SEMANTICANALYSIS_HPP
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
#define make_task_base(start, type, captures, function_body) make_pair(type_index(typeid(type)), [captures](const ParseTree& parsedTree, unsigned int& index) { start; function_body })
|
#define make_task_base(start, type, captures, function_body) make_pair(type_index(typeid(type)), [captures](const ParseTree& parsedTree, unsigned int& index) { start; function_body })
|
||||||
#define make_task_base_R(T, C, F) make_task_base(const T& parseComponent = reinterpret_cast<T&>(*parsedTree[index]), T, C, F)
|
#define make_task_base_R(T, C, F) make_task_base(const T& parseComponent = reinterpret_cast<T&>(*parsedTree[index]), T, C, F)
|
||||||
|
#define make_task(T, F) make_task_base_R(T, this, F)
|
||||||
|
#define make_task_noR(T, F) make_task_base(,T, this, F)
|
||||||
|
#define make_nonlocal_task(T, F) make_task_base_R(T, , F)
|
||||||
|
#define share_task(T, T2) make_task_noR(T2, this->getTaskMapInstance()[typeid(T)](parsedTree, index);)
|
||||||
|
|
||||||
class Tasking {
|
class Tasking {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -105,12 +105,12 @@ public:
|
||||||
#undef IS_PARSECOMPONENT
|
#undef IS_PARSECOMPONENT
|
||||||
|
|
||||||
namespace StandardComponents {
|
namespace StandardComponents {
|
||||||
struct Define: NamedIdentifier<true> {
|
template<bool BOOL>
|
||||||
const bool final;
|
struct Define: NamedIdentifier<BOOL> {
|
||||||
|
const bool final = BOOL;
|
||||||
ParseTree content;
|
ParseTree content;
|
||||||
explicit Define(const bool& isFinal, string_view nameText, ParseTree&& content): NamedIdentifier(nameText), final(isFinal), content(move(content)) {}
|
explicit Define(string_view nameText, ParseTree&& content): NamedIdentifier<BOOL>(nameText), content(move(content)) {}
|
||||||
explicit Define(string_view nameText, ParseTree&& content): Define(false, nameText, move(content)) {}
|
Define(Define&& define) noexcept: Define(define.name, move(define.content)) {}
|
||||||
Define(Define&& define) noexcept: Define(define.final, define.name, move(define.content)) {}
|
|
||||||
};
|
};
|
||||||
struct Reference: NamedIdentifier<false> {
|
struct Reference: NamedIdentifier<false> {
|
||||||
using NamedIdentifier::NamedIdentifier;
|
using NamedIdentifier::NamedIdentifier;
|
||||||
|
|
|
@ -134,19 +134,20 @@ namespace Parser {
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
} else i -= parametersDistance;
|
} else i -= parametersDistance;
|
||||||
|
|
||||||
// TODO Move this to semantic analysis
|
|
||||||
bool isFinalDefine = nextAre({TAG, DEFINE});
|
bool isFinalDefine = nextAre({TAG, DEFINE});
|
||||||
if (isFinalDefine || next.toktype == DEFINE) {
|
if (isFinalDefine || next.toktype == DEFINE) {
|
||||||
const optional previousDefinition = parseTree.template findReferenceByName<Define>(current.toktext);
|
|
||||||
if (previousDefinition.has_value() && (previousDefinition.value().get().final || isFinalDefine))
|
|
||||||
parsingError(current, previousDefinition->get().final ? " cannot be redefined as it is final" : " cannot be made final after it has been declared", true);
|
|
||||||
const unsigned increment = 2 + isFinalDefine;
|
const unsigned increment = 2 + isFinalDefine;
|
||||||
const auto beginning = lexed.begin() + i + increment;
|
const auto beginning = lexed.begin() + i + increment;
|
||||||
const auto end = find_if(beginning, lexed.end(), [¤t](const tok& it){
|
const auto end = find_if(beginning, lexed.end(), [¤t](const tok& it){
|
||||||
return it.toktype == SEMICOLON || it.line != current.line;
|
return it.toktype == SEMICOLON || it.line != current.line;
|
||||||
});
|
});
|
||||||
parseTree << Define(isFinalDefine, current.toktext, parse(beginning, end));
|
if (isFinalDefine) {
|
||||||
|
parseTree << Define<true>(current.toktext, parse(beginning, end));
|
||||||
|
} else {
|
||||||
|
parseTree << Define<false>(current.toktext, parse(beginning, end));
|
||||||
|
}
|
||||||
|
|
||||||
i += 1 + isFinalDefine + distance(beginning, end);
|
i += 1 + isFinalDefine + distance(beginning, end);
|
||||||
} else {
|
} else {
|
||||||
const bool method = nextAre({DOT, IDENTIFIER, LPAR});
|
const bool method = nextAre({DOT, IDENTIFIER, LPAR});
|
||||||
|
@ -184,23 +185,6 @@ namespace Parser {
|
||||||
} catch (const NamedIdentifier<true>::identifier_reserved_exception&) {
|
} catch (const NamedIdentifier<true>::identifier_reserved_exception&) {
|
||||||
parsingError(current, " is a reserved identifier", true);
|
parsingError(current, " is a reserved identifier", true);
|
||||||
}
|
}
|
||||||
// TODO Move this to semantic analysis
|
|
||||||
if (not parseTree.empty()) {
|
|
||||||
const auto& last = parseTree.cend() - 1;
|
|
||||||
const type_info& lastId = last->get()->getId();
|
|
||||||
const auto* last_identifier = dynamic_cast<NamedIdentifier<true>*>(last->get());
|
|
||||||
if (last_identifier != nullptr) {
|
|
||||||
if (lastId != typeid(Define) and
|
|
||||||
any_of(parseTree.cbegin(), last, [&last_identifier](const component_ptr& pointer){
|
|
||||||
try {
|
|
||||||
return dynamic_cast<NamedIdentifier<true>&>(*pointer).name == last_identifier->name;
|
|
||||||
} catch (const bad_cast&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
{ parsingError(current, " has already been defined previously", true); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return parseTree;
|
return parseTree;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,6 @@ protected:
|
||||||
}
|
}
|
||||||
} else output << openCharacters << view << closeCharacters;
|
} else output << openCharacters << view << closeCharacters;
|
||||||
}
|
}
|
||||||
#define make_task(T, F) make_task_base_R(T, this, F)
|
|
||||||
#define make_task_noR(T, F) make_task_base(,T, this, F)
|
|
||||||
#define make_nonlocal_task(T, F) make_task_base_R(T, , F)
|
|
||||||
typedef pair<const char*, const char*> print_functions_pair;
|
typedef pair<const char*, const char*> print_functions_pair;
|
||||||
virtual unordered_task_map getTaskMap() = 0;
|
virtual unordered_task_map getTaskMap() = 0;
|
||||||
virtual print_functions_pair printFunctions() = 0;
|
virtual print_functions_pair printFunctions() = 0;
|
||||||
|
@ -135,7 +132,8 @@ public:
|
||||||
output << ')';
|
output << ')';
|
||||||
),
|
),
|
||||||
make_task(StandardComponents::types::Integer, output << setprecision(parseComponent.precision) << fixed << parseComponent.value;),
|
make_task(StandardComponents::types::Integer, output << setprecision(parseComponent.precision) << fixed << parseComponent.value;),
|
||||||
make_task(StandardComponents::Condition, output << '('; transpileTree(parseComponent); output << ')';)
|
make_task(StandardComponents::Condition, output << '('; transpileTree(parseComponent); output << ')';),
|
||||||
|
share_task(StandardComponents::Define<false>, StandardComponents::Define<true>)
|
||||||
}));
|
}));
|
||||||
return fullMap;
|
return fullMap;
|
||||||
};
|
};
|
||||||
|
@ -163,11 +161,6 @@ unique_ptr<Target> Target::forName(string_view name, const bool newLines = true)
|
||||||
ADDTARGET("py", PyTarget);
|
ADDTARGET("py", PyTarget);
|
||||||
ADDTARGET("gd", GsTarget);
|
ADDTARGET("gd", GsTarget);
|
||||||
#undef ADDTARGET
|
#undef ADDTARGET
|
||||||
#undef make_nonlocal_task
|
|
||||||
#undef make_task_noR
|
|
||||||
#undef make_task
|
|
||||||
#undef make_task_base_R
|
|
||||||
#undef make_task_base
|
|
||||||
Yerbacon::fail({"\"", name.data(), "\" is not a valid target."});
|
Yerbacon::fail({"\"", name.data(), "\" is not a valid target."});
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ struct GsTarget: Target {
|
||||||
print_functions_pair printFunctions() final { return make_pair("printraw", "print"); }
|
print_functions_pair printFunctions() final { return make_pair("printraw", "print"); }
|
||||||
unordered_task_map getTaskMap() final {
|
unordered_task_map getTaskMap() final {
|
||||||
return {
|
return {
|
||||||
make_task(Define,
|
make_task(Define<false>,
|
||||||
output << (parseComponent.final ? "const " : "var ") << parseComponent.name << " = ";
|
output << (parseComponent.final ? "const " : "var ") << parseComponent.name << " = ";
|
||||||
transpileTree(parseComponent.content);
|
transpileTree(parseComponent.content);
|
||||||
),
|
),
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct JsTarget: Target {
|
||||||
bool use_uniqueLineSeparator() final { return true; }
|
bool use_uniqueLineSeparator() final { return true; }
|
||||||
unordered_task_map getTaskMap() final {
|
unordered_task_map getTaskMap() final {
|
||||||
return {
|
return {
|
||||||
make_task(Define,
|
make_task(Define<false>,
|
||||||
output << (parseComponent.final ? "const " : "let ") << parseComponent.name << " = ";
|
output << (parseComponent.final ? "const " : "let ") << parseComponent.name << " = ";
|
||||||
transpileTree(parseComponent.content);
|
transpileTree(parseComponent.content);
|
||||||
),
|
),
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct LuaTarget: Target {
|
||||||
optional_string uniqueLineSeparator() final { return " "; }
|
optional_string uniqueLineSeparator() final { return " "; }
|
||||||
unordered_task_map getTaskMap() final {
|
unordered_task_map getTaskMap() final {
|
||||||
return {
|
return {
|
||||||
make_task(Define,
|
make_task(Define<false>,
|
||||||
if (parseComponent.final) output << "local ";
|
if (parseComponent.final) output << "local ";
|
||||||
output << parseComponent.name;
|
output << parseComponent.name;
|
||||||
if (parseComponent.final) output << " <const>"; // TODO Find an alternative to <const> for lua <5.4
|
if (parseComponent.final) output << " <const>"; // TODO Find an alternative to <const> for lua <5.4
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct PyTarget: Target {
|
||||||
optional_string uniqueLineSeparator() final { return {}; }
|
optional_string uniqueLineSeparator() final { return {}; }
|
||||||
unordered_task_map getTaskMap() final {
|
unordered_task_map getTaskMap() final {
|
||||||
return {
|
return {
|
||||||
make_task(Define, output << parseComponent.name << " = "; transpileTree(parseComponent.content);),
|
make_task(Define<false>, output << parseComponent.name << " = "; transpileTree(parseComponent.content);),
|
||||||
make_task(types::String, stringInterpolation(R"(""")", parseComponent.content);),
|
make_task(types::String, stringInterpolation(R"(""")", parseComponent.content);),
|
||||||
make_task(Function,
|
make_task(Function,
|
||||||
output << "def " << parseComponent.name << '(';
|
output << "def " << parseComponent.name << '(';
|
||||||
|
|
Loading…
Reference in New Issue