#ifndef YERBACON_PARSECOMPONENTS_HPP #define YERBACON_PARSECOMPONENTS_HPP #include #include #include #include #include #include #include using namespace std; #include "../lex.hpp" #define IS(X) template::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 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(it); }); } IS(StandardComponents::NamedIdentifier) optional> findByName(const string& name) const { auto identifiers = findById(); for (T* identifier: identifiers) { if (identifier->getId() == typeid(T) && identifier->name == name) { return make_optional(ref(*identifier)); } } return optional>(); }; 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& 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& elements): ParseTree() { addAll(elements); } ~ParseTree() { for (const auto& pointer: subComponents) { delete pointer; } } }; #undef IS_PARSECOMPONENT #endif //YERBACON_PARSECOMPONENTS_HPP