diff --git a/src/headers/parsing/ParseComponents.hpp b/src/headers/parsing/ParseComponents.hpp index 6a1c619..ef81f7d 100644 --- a/src/headers/parsing/ParseComponents.hpp +++ b/src/headers/parsing/ParseComponents.hpp @@ -4,51 +4,96 @@ #include #include #include +#include +#include +#include +#include using namespace std; #include "../lex.hpp" -struct ParseComponent { - virtual ~ParseComponent() = default; -}; -class ParseTree: public ParseComponent { -protected: - mutable vector subComponents; -public: - size_t getCompCount() const { return subComponents.size(); } - auto& getComponents() const { return subComponents; } - void add(const ParseComponent& component) const { - subComponents.push_back(component); - }; void addAll(const vector& components) const { - for (const auto& comp: components) add(comp); - } - const ParseTree& operator<<(const ParseComponent& component) const { add(component); return *this; } - explicit ParseTree(const ParseComponent& element): subComponents() { add(element); } - ParseTree(const initializer_list& elements): subComponents() { addAll(elements); } - ParseTree(): subComponents() {}; +#define IS(X) template::value>::type* = nullptr> +#define IS_PARSECOMPONENT IS(ParseComponent) +struct ParseComponent { + [[nodiscard]] const type_info& getId() const { return typeid(*this); } + ParseComponent() = default; + virtual ~ParseComponent() = default; }; namespace StandardComponents { struct [[deprecated]] Expression: ParseComponent {}; - struct Define: ParseComponent { - const bool final; - explicit Define(const bool& isFinal): final(isFinal) {} - // Shorthand for Define(false) - Define(): Define(false) {} - }; - struct Class: ParseComponent { - struct Constructor {}; + struct NamedIdentifier: public ParseComponent { const string name; + explicit NamedIdentifier(string_view nameText): ParseComponent(), 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; - explicit Class(string_view text): name(text) {} + using NamedIdentifier::NamedIdentifier; }; namespace types { struct String: ParseComponent { - [[maybe_unused]] const char* content; - explicit String(const char* string): content(string) {} + const char* content; + explicit String(const char* string): ParseComponent(), content(string) {} }; } } +class ParseTree { +protected: + mutable vector subComponents; +public: + IS(StandardComponents::NamedIdentifier) + optional> findByName(const string& name) { + auto identifiers = findById(); + for (const auto& identifier: identifiers) { + if (identifier.name == name) { + return identifier; + } + } + return optional>(); + }; + IS_PARSECOMPONENT + auto findById() const { + bool typeFoundOnce = false; + auto foundPointers = 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); + }); + return foundPointers; + } + 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)); + }; void addAll(const vector& 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 \ No newline at end of file diff --git a/src/headers/parsing/Parser.hpp b/src/headers/parsing/Parser.hpp index 55ac23c..b30109b 100644 --- a/src/headers/parsing/Parser.hpp +++ b/src/headers/parsing/Parser.hpp @@ -2,8 +2,7 @@ #define YERBACON_PARSER_HPP #include -#include "../lex.hpp" -#include "../parsing/ParseComponents.hpp" +#include "ParseComponents.hpp" #include "../Yerbacon.hpp" namespace Parser { @@ -22,14 +21,13 @@ namespace Parser { case tok::IDENTIFIER: { if (current.toktext == "class") { if (next.toktype == tok::IDENTIFIER) { - parseTree << Class(next.toktext); - ++i; continue; + parseTree << Class(next.toktext); ++i; } else throw ParsingException('"' + next.toktext + "\" is not a valid class identifier"); } else { - if (next.toktype == tok::TAG && (lexed.size() - i) > 2 && lexed[i + 2].toktype == tok::DEFINE) { - parseTree << Define(true); i += 2; - } else if (next.toktype == tok::DEFINE) { - parseTree << Define(); ++i; + const bool isFinalDefine = next.toktype == tok::TAG && (lexed.size() - i) > 2 && lexed[i + 2].toktype == tok::DEFINE; + if (isFinalDefine || next.toktype == tok::DEFINE) { + parseTree << Define(isFinalDefine, current.toktext); + i += isFinalDefine ? 2 : 1; } } }