Use runtime type information in ParseComponents.hpp.
This commit is contained in:
parent
c23d88e0eb
commit
fa546865a0
|
@ -4,51 +4,96 @@
|
|||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
using namespace std;
|
||||
|
||||
#include "../lex.hpp"
|
||||
|
||||
struct ParseComponent {
|
||||
virtual ~ParseComponent() = default;
|
||||
};
|
||||
|
||||
class ParseTree: public ParseComponent {
|
||||
protected:
|
||||
mutable vector<ParseComponent> subComponents;
|
||||
public:
|
||||
size_t getCompCount() const { return subComponents.size(); }
|
||||
auto& getComponents() const { return subComponents; }
|
||||
void add(const ParseComponent& component) const {
|
||||
subComponents.push_back(component);
|
||||
}; void addAll(const vector<ParseComponent>& components) const {
|
||||
for (const auto& comp: components) add(comp);
|
||||
}
|
||||
const ParseTree& operator<<(const ParseComponent& component) const { add(component); return *this; }
|
||||
explicit ParseTree(const ParseComponent& element): subComponents() { add(element); }
|
||||
ParseTree(const initializer_list<ParseComponent>& elements): subComponents() { addAll(elements); }
|
||||
ParseTree(): subComponents() {};
|
||||
#define IS(X) template<typename T, typename std::enable_if<std::is_base_of<X, T>::value>::type* = nullptr>
|
||||
#define IS_PARSECOMPONENT IS(ParseComponent)
|
||||
struct ParseComponent {
|
||||
[[nodiscard]] const type_info& getId() const { return typeid(*this); }
|
||||
ParseComponent() = default;
|
||||
virtual ~ParseComponent() = default;
|
||||
};
|
||||
|
||||
namespace StandardComponents {
|
||||
struct [[deprecated]] Expression: ParseComponent {};
|
||||
struct Define: ParseComponent {
|
||||
const bool final;
|
||||
explicit Define(const bool& isFinal): final(isFinal) {}
|
||||
// Shorthand for Define(false)
|
||||
Define(): Define(false) {}
|
||||
};
|
||||
struct Class: ParseComponent {
|
||||
struct Constructor {};
|
||||
struct NamedIdentifier: public ParseComponent {
|
||||
const string name;
|
||||
explicit NamedIdentifier(string_view nameText): ParseComponent(), name(nameText) {}
|
||||
};
|
||||
struct Define: NamedIdentifier {
|
||||
const bool final;
|
||||
explicit Define(const bool& isFinal, string_view nameText): NamedIdentifier(nameText), final(isFinal) {}
|
||||
explicit Define(string_view nameText): Define(false, nameText) {}
|
||||
};
|
||||
|
||||
struct Class: NamedIdentifier {
|
||||
struct Constructor {};
|
||||
Constructor constructor;
|
||||
explicit Class(string_view text): name(text) {}
|
||||
using NamedIdentifier::NamedIdentifier;
|
||||
};
|
||||
namespace types {
|
||||
struct String: ParseComponent {
|
||||
[[maybe_unused]] const char* content;
|
||||
explicit String(const char* string): content(string) {}
|
||||
const char* content;
|
||||
explicit String(const char* string): ParseComponent(), content(string) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class ParseTree {
|
||||
protected:
|
||||
mutable vector<ParseComponent*> subComponents;
|
||||
public:
|
||||
IS(StandardComponents::NamedIdentifier)
|
||||
optional<reference_wrapper<T>> findByName(const string& name) {
|
||||
auto identifiers = findById<StandardComponents::NamedIdentifier>();
|
||||
for (const auto& identifier: identifiers) {
|
||||
if (identifier.name == name) {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
return optional<reference_wrapper<T>>();
|
||||
};
|
||||
IS_PARSECOMPONENT
|
||||
auto findById() const {
|
||||
bool typeFoundOnce = false;
|
||||
auto foundPointers = subComponents | views::filter([&typeFoundOnce](const ParseComponent* it) {
|
||||
const bool typeFound = it->getId() == typeid(T);
|
||||
if (typeFound) typeFoundOnce = true;
|
||||
return typeFound;
|
||||
}) | views::transform([](ParseComponent* it) {
|
||||
return reinterpret_cast<T&>(*it);
|
||||
});
|
||||
return foundPointers;
|
||||
}
|
||||
inline size_t getCompCount() const { return subComponents.size(); }
|
||||
auto& getComponents() { return subComponents; }
|
||||
auto getComponents() const { return subComponents; }
|
||||
IS_PARSECOMPONENT
|
||||
void add(const T& component) const {
|
||||
subComponents.push_back(new T(component));
|
||||
}; void addAll(const vector<ParseComponent>& components) const {
|
||||
for (const auto& comp: components) add(comp);
|
||||
}
|
||||
IS_PARSECOMPONENT
|
||||
const ParseTree& operator<<(const T& component) const { add(component); return *this; }
|
||||
ParseTree(): subComponents() {};
|
||||
IS_PARSECOMPONENT
|
||||
explicit ParseTree(const T& element): ParseTree() { add(element); }
|
||||
IS_PARSECOMPONENT
|
||||
ParseTree(const initializer_list<T>& elements): ParseTree() { addAll(elements); }
|
||||
~ParseTree() {
|
||||
for (const auto& pointer: subComponents) {
|
||||
delete pointer;
|
||||
}
|
||||
}
|
||||
};
|
||||
#undef IS_PARSECOMPONENT
|
||||
|
||||
#endif //YERBACON_PARSECOMPONENTS_HPP
|
|
@ -2,8 +2,7 @@
|
|||
#define YERBACON_PARSER_HPP
|
||||
|
||||
#include <string>
|
||||
#include "../lex.hpp"
|
||||
#include "../parsing/ParseComponents.hpp"
|
||||
#include "ParseComponents.hpp"
|
||||
#include "../Yerbacon.hpp"
|
||||
|
||||
namespace Parser {
|
||||
|
@ -22,14 +21,13 @@ namespace Parser {
|
|||
case tok::IDENTIFIER: {
|
||||
if (current.toktext == "class") {
|
||||
if (next.toktype == tok::IDENTIFIER) {
|
||||
parseTree << Class(next.toktext);
|
||||
++i; continue;
|
||||
parseTree << Class(next.toktext); ++i;
|
||||
} else throw ParsingException('"' + next.toktext + "\" is not a valid class identifier");
|
||||
} else {
|
||||
if (next.toktype == tok::TAG && (lexed.size() - i) > 2 && lexed[i + 2].toktype == tok::DEFINE) {
|
||||
parseTree << Define(true); i += 2;
|
||||
} else if (next.toktype == tok::DEFINE) {
|
||||
parseTree << Define(); ++i;
|
||||
const bool isFinalDefine = next.toktype == tok::TAG && (lexed.size() - i) > 2 && lexed[i + 2].toktype == tok::DEFINE;
|
||||
if (isFinalDefine || next.toktype == tok::DEFINE) {
|
||||
parseTree << Define(isFinalDefine, current.toktext);
|
||||
i += isFinalDefine ? 2 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue