#ifndef YERBACON_PARSECOMPONENTS_HPP #define YERBACON_PARSECOMPONENTS_HPP #include #include #include #include #include #include #include #include using namespace std; #include "../lex.hpp" #include #define IS(X) template 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> 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& components ) const { subComponents.reserve(components.size()); for (const T& current: components) addComponent(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 findById() const { vector filteredComponents; for_each(cbegin(), cend(), [&filteredComponents](const unique_ptr& it) { if (it->getId() == typeid(T)) { filteredComponents.push_back(reinterpret_cast(it.get())); } }); return filteredComponents; } IS(StandardComponents::NamedIdentifier) optional> findReferenceByName(const string& name) const { auto identifiers = findById(); for (const auto& identifier: identifiers) { if (identifier->getId() == typeid(T) && identifier->name == name) { return make_optional(ref(static_cast(*identifier))); } } return optional>(); }; 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(key); } inline size_t getCompCount() const { return subComponents.size(); } IS_PARSECOMPONENT inline void add(const T& component) { addComponent(component); } IS_PARSECOMPONENT inline void addAll(const initializer_list& components) { addAllComponents(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& elements): ParseTree() { addAllComponents(elements); } ParseTree(const initializer_list& elements): ParseTree() { for_each(elements.begin(), elements.end(), [&](ParseComponent* component){ subComponents.emplace_back(component); }); } }; #undef IS_PARSECOMPONENT #endif //YERBACON_PARSECOMPONENTS_HPP