From 905e7e7e8221ee44c3cca9576f88e4d623943970 Mon Sep 17 00:00:00 2001 From: Username404 Date: Thu, 29 Jul 2021 17:35:35 +0200 Subject: [PATCH] Add lexing and parsing exceptions and parse = and #= --- src/etc/lexer.cpp | 2 +- src/headers/Yerbacon.hpp | 12 ++++++++++ src/headers/lex.hpp | 6 +++-- src/headers/parsing/ParseComponents.hpp | 31 +++++++++++++++++++------ src/headers/parsing/Parser.hpp | 27 ++++++++++++++++++--- 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/etc/lexer.cpp b/src/etc/lexer.cpp index bc58ca9..87c5619 100644 --- a/src/etc/lexer.cpp +++ b/src/etc/lexer.cpp @@ -1,5 +1,4 @@ #include "../headers/lex.hpp" -#include using namespace std; tok::type getIdentifierCharType(const char& Char) { @@ -41,6 +40,7 @@ vector lex(const string& in) for (;i < in.size(); ++i) { tok::type currentCharType = getIdentifierCharType(in[i]); bool isString = currentCharType == tok::STRING; + if (i == in.size() - 1 && not isString) throw tok::LexerException("A never ending string was found"); if ((currentCharType == type || isTypeString) && !isString) { formedString += string(1, in[i]); } else { diff --git a/src/headers/Yerbacon.hpp b/src/headers/Yerbacon.hpp index 7242b1a..8abb671 100644 --- a/src/headers/Yerbacon.hpp +++ b/src/headers/Yerbacon.hpp @@ -6,8 +6,20 @@ #define YBCON_VERSION "UNKNOWN" #endif +#include +#include +#include + namespace Yerbacon { consteval const char* getVersion() noexcept { return YBCON_VERSION; } + class Exception: public std::exception { + std::string exceptionCause; + [[nodiscard]] const char* what() const noexcept override { + return exceptionCause.data(); + } + public: + explicit Exception(const std::string_view& cause): exceptionCause(cause) {} + }; } #endif \ No newline at end of file diff --git a/src/headers/lex.hpp b/src/headers/lex.hpp index 7031e54..ac2792b 100644 --- a/src/headers/lex.hpp +++ b/src/headers/lex.hpp @@ -2,11 +2,13 @@ #define YERBACON_LEX_H #include -#include -#include +#include "Yerbacon.hpp" #include struct tok { + class LexerException: public Yerbacon::Exception { + using Yerbacon::Exception::Exception; + }; enum type { DEFINE, TAG, NUMBER, PLUS, LPAR, LBRACE, LBRACKET, RPAR, RBRACE, RBRACKET, ALPHACHAR, HYPHEN, LCOMP, RCOMP, SQUOTE, diff --git a/src/headers/parsing/ParseComponents.hpp b/src/headers/parsing/ParseComponents.hpp index 0f8d99e..a40aad0 100644 --- a/src/headers/parsing/ParseComponents.hpp +++ b/src/headers/parsing/ParseComponents.hpp @@ -8,30 +8,47 @@ using namespace std; #include "../lex.hpp" -class ParseComponent {}; +struct ParseComponent { + virtual ~ParseComponent() = default; +}; class ParseTree: public ParseComponent { -private: - mutable unsigned int compCount = 0; protected: mutable vector subComponents; public: - constexpr unsigned int getCompCount() const { return compCount; } + size_t getCompCount() const { return subComponents.size(); } auto& getComponents() const { return subComponents; } void add(const ParseComponent& component) const { subComponents.push_back(component); - ++compCount; }; void addAll(const vector& components) const { for (const auto& comp: components) add(comp); }; void operator<<(const ParseComponent& component) const { add(component); } explicit ParseTree(const ParseComponent& element): subComponents() { add(element); } ParseTree(const initializer_list& elements): subComponents() { addAll(elements); } ParseTree(): subComponents() {}; - ~ParseTree() = default; }; -namespace StandardComponents::types { +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 Constructor: ParseComponent {}; + struct ClassBody: ParseComponent {}; + struct Class: ParseComponent { + string bullshitText; + Constructor constructor; + explicit Class(string_view text): bullshitText(text) {} + }; + namespace types { + struct String: ParseComponent { + [[maybe_unused]] const char* content; + explicit String(const char* string): content(string) {} + }; + } } #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 25c336f..55ac23c 100644 --- a/src/headers/parsing/Parser.hpp +++ b/src/headers/parsing/Parser.hpp @@ -4,18 +4,39 @@ #include #include "../lex.hpp" #include "../parsing/ParseComponents.hpp" +#include "../Yerbacon.hpp" namespace Parser { + class ParsingException: public Yerbacon::Exception { + using Yerbacon::Exception::Exception; + }; ParseTree parseVector(const vector& lexed) { ParseTree parseTree; - using namespace StandardComponents::types; + using namespace StandardComponents; if (lexed.size() > 1) { for (unsigned int i = 0; i < lexed.size() - 1; ++i) { const auto& current = lexed[i], next = lexed[i + 1]; - + switch (current.toktype) { + case tok::STRING: parseTree << types::String(current.toktext.data()); break; + case tok::IDENTIFIER: { + if (current.toktext == "class") { + if (next.toktype == tok::IDENTIFIER) { + parseTree << Class(next.toktext); + ++i; continue; + } 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; + } + } + } + default: break; + } } - } + } else throw ParsingException("At least 2 tokens must be provided"); return parseTree; } }