Add lexing and parsing exceptions and parse = and #=

This commit is contained in:
Username404 2021-07-29 17:35:35 +02:00
parent ecc2683cea
commit 905e7e7e82
Signed by: Username404-59
GPG Key ID: 7AB361FBB257A5D1
5 changed files with 65 additions and 13 deletions

View File

@ -1,5 +1,4 @@
#include "../headers/lex.hpp" #include "../headers/lex.hpp"
#include <iostream>
using namespace std; using namespace std;
tok::type getIdentifierCharType(const char& Char) { tok::type getIdentifierCharType(const char& Char) {
@ -41,6 +40,7 @@ vector<tok> lex(const string& in)
for (;i < in.size(); ++i) { for (;i < in.size(); ++i) {
tok::type currentCharType = getIdentifierCharType(in[i]); tok::type currentCharType = getIdentifierCharType(in[i]);
bool isString = currentCharType == tok::STRING; 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) { if ((currentCharType == type || isTypeString) && !isString) {
formedString += string(1, in[i]); formedString += string(1, in[i]);
} else { } else {

View File

@ -6,8 +6,20 @@
#define YBCON_VERSION "UNKNOWN" #define YBCON_VERSION "UNKNOWN"
#endif #endif
#include <exception>
#include <string_view>
#include <string>
namespace Yerbacon { namespace Yerbacon {
consteval const char* getVersion() noexcept { return YBCON_VERSION; } 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 #endif

View File

@ -2,11 +2,13 @@
#define YERBACON_LEX_H #define YERBACON_LEX_H
#include <vector> #include <vector>
#include <string> #include "Yerbacon.hpp"
#include <string_view>
#include <ostream> #include <ostream>
struct tok { struct tok {
class LexerException: public Yerbacon::Exception {
using Yerbacon::Exception::Exception;
};
enum type { enum type {
DEFINE, TAG, NUMBER, PLUS, LPAR, LBRACE, LBRACKET, RPAR, RBRACE, RBRACKET, ALPHACHAR, HYPHEN, LCOMP, RCOMP, DEFINE, TAG, NUMBER, PLUS, LPAR, LBRACE, LBRACKET, RPAR, RBRACE, RBRACKET, ALPHACHAR, HYPHEN, LCOMP, RCOMP,
SQUOTE, SQUOTE,

View File

@ -8,30 +8,47 @@ using namespace std;
#include "../lex.hpp" #include "../lex.hpp"
class ParseComponent {}; struct ParseComponent {
virtual ~ParseComponent() = default;
};
class ParseTree: public ParseComponent { class ParseTree: public ParseComponent {
private:
mutable unsigned int compCount = 0;
protected: protected:
mutable vector<ParseComponent> subComponents; mutable vector<ParseComponent> subComponents;
public: public:
constexpr unsigned int getCompCount() const { return compCount; } size_t getCompCount() const { return subComponents.size(); }
auto& getComponents() const { return subComponents; } auto& getComponents() const { return subComponents; }
void add(const ParseComponent& component) const { void add(const ParseComponent& component) const {
subComponents.push_back(component); subComponents.push_back(component);
++compCount;
}; void addAll(const vector<ParseComponent>& components) const { }; void addAll(const vector<ParseComponent>& components) const {
for (const auto& comp: components) add(comp); for (const auto& comp: components) add(comp);
}; void operator<<(const ParseComponent& component) const { add(component); } }; void operator<<(const ParseComponent& component) const { add(component); }
explicit ParseTree(const ParseComponent& element): subComponents() { add(element); } explicit ParseTree(const ParseComponent& element): subComponents() { add(element); }
ParseTree(const initializer_list<ParseComponent>& elements): subComponents() { addAll(elements); } ParseTree(const initializer_list<ParseComponent>& elements): subComponents() { addAll(elements); }
ParseTree(): subComponents() {}; ParseTree(): subComponents() {};
~ParseTree() = default;
}; };
namespace StandardComponents::types { namespace StandardComponents {
struct [[deprecated]] Expression: ParseComponent {}; 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 #endif //YERBACON_PARSECOMPONENTS_HPP

View File

@ -4,18 +4,39 @@
#include <string> #include <string>
#include "../lex.hpp" #include "../lex.hpp"
#include "../parsing/ParseComponents.hpp" #include "../parsing/ParseComponents.hpp"
#include "../Yerbacon.hpp"
namespace Parser { namespace Parser {
class ParsingException: public Yerbacon::Exception {
using Yerbacon::Exception::Exception;
};
ParseTree parseVector(const vector<tok>& lexed) { ParseTree parseVector(const vector<tok>& lexed) {
ParseTree parseTree; ParseTree parseTree;
using namespace StandardComponents::types; using namespace StandardComponents;
if (lexed.size() > 1) { if (lexed.size() > 1) {
for (unsigned int i = 0; i < lexed.size() - 1; ++i) { for (unsigned int i = 0; i < lexed.size() - 1; ++i) {
const auto& current = lexed[i], next = lexed[i + 1]; 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; return parseTree;
} }
} }