Move redefinition checking to SemanticAnalysis.hpp
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
This commit is contained in:
parent
7fb9ca37a7
commit
2c0cec16d6
|
@ -4,7 +4,13 @@
|
||||||
#include "parsing/ParseComponents.hpp"
|
#include "parsing/ParseComponents.hpp"
|
||||||
#include "Tasking.hpp"
|
#include "Tasking.hpp"
|
||||||
|
|
||||||
|
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) {
|
||||||
|
@ -15,9 +21,25 @@ 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),
|
||||||
|
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"));
|
||||||
|
)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define make_task(T, F) make_task_base_R(T, this, 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_task_noR(T, F) make_task_base(,T, this, F)
|
||||||
#define make_nonlocal_task(T, F) make_task_base_R(T, , 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:
|
||||||
|
|
|
@ -134,13 +134,9 @@ 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){
|
||||||
|
@ -184,23 +180,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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue