Move redefinition checking to SemanticAnalysis.hpp

Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
This commit is contained in:
Username404-59 2024-12-31 19:59:02 +01:00
parent 7fb9ca37a7
commit 2c0cec16d6
Signed by: Username404-59
GPG Key ID: 7AB361FBB257A5D1
3 changed files with 26 additions and 24 deletions

View File

@ -4,7 +4,13 @@
#include "parsing/ParseComponents.hpp"
#include "Tasking.hpp"
using namespace StandardComponents;
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& task_map = getTaskMapInstance();
for (unsigned int i = 0; i < tree.size(); ++i) {
@ -15,9 +21,25 @@ struct SemanticAnalyser final: public Tasking {
return tree;
}
private:
unordered_task_map getTaskMapInstance() final {
unordered_task_map getTaskMapInstance() final { // TODO Include line in error messages
using namespace StandardComponents;
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),
make_nonlocal_task(Define,
const optional previousDefinition = parsedTree.findReferenceByName<Define>(parseComponent.name).value();
if (&previousDefinition.value().get() != &parseComponent && (previousDefinition.value().get().final || parseComponent.final))
error(parseComponent.name + string(previousDefinition->get().final ? " cannot be redefined as it is final" : " cannot be made final after it has been declared"));
)
};
};
};

View File

@ -10,6 +10,7 @@
#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 {
protected:

View File

@ -135,12 +135,8 @@ namespace Parser {
break;
} else i -= parametersDistance;
// TODO Move this to semantic analysis
bool isFinalDefine = nextAre({TAG, 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 auto beginning = lexed.begin() + i + increment;
const auto end = find_if(beginning, lexed.end(), [&current](const tok& it){
@ -184,23 +180,6 @@ namespace Parser {
} catch (const NamedIdentifier<true>::identifier_reserved_exception&) {
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;
}