Yerbacon/src/headers/parsing/ParseComponents.hpp
Username404 f33aec687a
Parse Calls/ParseTrees
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2022-02-14 14:12:00 +01:00

113 lines
4.5 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]] inline const type_info& getId() const { return typeid(*this); }
virtual ~ParseComponent() = default;
};
struct NamedIdentifier: ParseComponent {
const string name;
explicit NamedIdentifier(string_view nameText): name(nameText) {}
};
#define IS_PARSECOMPONENT IS(ParseComponent)
class ParseTree: public ParseComponent {
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 {
if constexpr(is_copy_constructible_v<T>) {
subComponents.emplace_back(new T(component));
} else {
static_assert(is_move_constructible_v<T>, "T is not copy-constructible or move-constructible");
subComponents.emplace_back(new T(move(const_cast<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 size_t size() const { return subComponents.size(); }
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(NamedIdentifier)
optional<reference_wrapper<T>> findReferenceByName(const string& name) const {
const vector<T*> identifiers = findById<T>();
for (T* 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(NamedIdentifier)
inline auto operator[](const string& key) const { return findReferenceByName<T>(key); }
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(ParseTree&& parseTree) noexcept: subComponents(move(parseTree.subComponents)) {}
ParseTree(const ParseTree& parseTree) = delete;
};
#undef IS_PARSECOMPONENT
namespace StandardComponents {
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;
};
namespace types {
struct String: ParseComponent {
const string content;
explicit String(const char* string): content(string) {}
};
}
struct Call: ParseTree { inline explicit Call(ParseTree&& tree) noexcept: ParseTree(move(tree)) {} };
struct Class: NamedIdentifier {
using NamedIdentifier::NamedIdentifier;
};
}
#endif //YERBACON_PARSECOMPONENTS_HPP