97 lines
3.2 KiB
C++
97 lines
3.2 KiB
C++
#ifndef YERBACON_PARSECOMPONENTS_HPP
|
|
#define YERBACON_PARSECOMPONENTS_HPP
|
|
|
|
#include <iostream>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include <typeinfo>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <ranges>
|
|
using namespace std;
|
|
|
|
#include "../lex.hpp"
|
|
|
|
|
|
#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); }
|
|
virtual ~ParseComponent() = default;
|
|
};
|
|
|
|
namespace StandardComponents {
|
|
struct [[deprecated]] Expression: ParseComponent {};
|
|
struct NamedIdentifier: public ParseComponent {
|
|
const string name;
|
|
explicit NamedIdentifier(string_view nameText): 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;
|
|
using NamedIdentifier::NamedIdentifier;
|
|
};
|
|
namespace types {
|
|
struct String: ParseComponent {
|
|
const char* content;
|
|
explicit String(const char* string): content(string) {}
|
|
};
|
|
}
|
|
}
|
|
|
|
class ParseTree {
|
|
protected:
|
|
mutable vector<ParseComponent*> subComponents;
|
|
public:
|
|
IS_PARSECOMPONENT
|
|
auto findById() const {
|
|
bool typeFoundOnce = false;
|
|
return 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);
|
|
});
|
|
}
|
|
IS(StandardComponents::NamedIdentifier)
|
|
optional<reference_wrapper<T>> findByName(const string& name) const {
|
|
auto identifiers = findById<T>();
|
|
for (T* identifier: identifiers) {
|
|
if (identifier->getId() == typeid(T) && identifier->name == name) {
|
|
return make_optional(ref(*identifier));
|
|
}
|
|
}
|
|
return optional<reference_wrapper<T>>();
|
|
};
|
|
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));
|
|
}; IS_PARSECOMPONENT void addAll(const initializer_list<T>& components) const {
|
|
for (const auto& comp: components) add<T>(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
|