110 lines
4.3 KiB
C++
110 lines
4.3 KiB
C++
#ifndef YERBACON_PARSECOMPONENTS_HPP
|
|
#define YERBACON_PARSECOMPONENTS_HPP
|
|
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include <typeinfo>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <algorithm>
|
|
using namespace std;
|
|
|
|
#include "../lex.hpp"
|
|
|
|
#include <concepts>
|
|
#define IS(X) template<derived_from<X> T = X>
|
|
struct ParseComponent {
|
|
[[nodiscard]] constexpr const type_info& getId() const { return typeid(*this); }
|
|
virtual ~ParseComponent() = default;
|
|
};
|
|
|
|
namespace StandardComponents {
|
|
struct NamedIdentifier: 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 Reference: NamedIdentifier {
|
|
using NamedIdentifier::NamedIdentifier;
|
|
};
|
|
|
|
struct Class: NamedIdentifier {
|
|
struct Constructor {};
|
|
Constructor constructor;
|
|
using NamedIdentifier::NamedIdentifier;
|
|
};
|
|
namespace types {
|
|
struct String: ParseComponent {
|
|
const string content;
|
|
explicit String(const char* string): content(string) {}
|
|
};
|
|
}
|
|
}
|
|
|
|
#define IS_PARSECOMPONENT IS(ParseComponent)
|
|
class ParseTree {
|
|
mutable vector<unique_ptr<ParseComponent>> subComponents;
|
|
using array_type = decltype(subComponents);
|
|
using iterator = array_type::iterator;
|
|
using constant_iterator = array_type::const_iterator;
|
|
protected:
|
|
IS_PARSECOMPONENT
|
|
void addComponent(const T& component) const
|
|
{ subComponents.emplace_back(new T(component)); };
|
|
IS_PARSECOMPONENT
|
|
void addAllComponents(
|
|
const initializer_list<T>& components
|
|
) const {
|
|
subComponents.reserve(components.size());
|
|
for (const T& current: components) addComponent<T>(current);
|
|
}
|
|
public:
|
|
inline iterator begin() const noexcept { return subComponents.begin(); }
|
|
inline constant_iterator cbegin() const noexcept { return subComponents.cbegin(); }
|
|
inline iterator end() const noexcept { return subComponents.end(); }
|
|
inline constant_iterator cend() const noexcept { return subComponents.cend(); }
|
|
IS_PARSECOMPONENT
|
|
vector<T*> findById() const {
|
|
vector<T*> filteredComponents;
|
|
for_each(cbegin(), cend(), [&filteredComponents](const unique_ptr<ParseComponent>& it) {
|
|
if (it->getId() == typeid(T)) {
|
|
filteredComponents.push_back(reinterpret_cast<T*>(it.get()));
|
|
}
|
|
});
|
|
return filteredComponents;
|
|
}
|
|
IS(StandardComponents::NamedIdentifier)
|
|
optional<reference_wrapper<T>> findReferenceByName(const string& name) const {
|
|
auto identifiers = findById<T>();
|
|
for (const auto& identifier: identifiers) {
|
|
if (identifier->getId() == typeid(T) && identifier->name == name) {
|
|
return make_optional(ref(static_cast<T&>(*identifier)));
|
|
}
|
|
}
|
|
return optional<reference_wrapper<T>>();
|
|
};
|
|
inline decltype(*subComponents.data()) operator[](const unsigned int& index) const { return subComponents[index]; }
|
|
IS(StandardComponents::NamedIdentifier)
|
|
inline auto operator[](const string& key) const { return findReferenceByName<T>(key); }
|
|
inline size_t getCompCount() const { return subComponents.size(); }
|
|
IS_PARSECOMPONENT inline void add(const T& component) { addComponent<T>(component); }
|
|
IS_PARSECOMPONENT inline void addAll(const initializer_list<T>& components) { addAllComponents<T>(components); }
|
|
IS_PARSECOMPONENT inline ParseTree& operator<<(const T& component) { add(component); return *this; }
|
|
ParseTree(): subComponents() {};
|
|
IS_PARSECOMPONENT constexpr explicit ParseTree(const T& element): ParseTree() { addComponent(element); }
|
|
IS_PARSECOMPONENT constexpr ParseTree(const initializer_list<T>& elements): ParseTree() { addAllComponents(elements); }
|
|
ParseTree(const initializer_list<ParseComponent*>& elements): ParseTree() {
|
|
for_each(elements.begin(), elements.end(), [&](ParseComponent* component){
|
|
subComponents.emplace_back(component);
|
|
});
|
|
}
|
|
};
|
|
#undef IS_PARSECOMPONENT
|
|
|
|
#endif //YERBACON_PARSECOMPONENTS_HPP
|