Add lexing and parsing exceptions and parse = and #=
This commit is contained in:
parent
ecc2683cea
commit
905e7e7e82
@ -1,5 +1,4 @@
|
||||
#include "../headers/lex.hpp"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
tok::type getIdentifierCharType(const char& Char) {
|
||||
@ -41,6 +40,7 @@ vector<tok> 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 {
|
||||
|
@ -6,8 +6,20 @@
|
||||
#define YBCON_VERSION "UNKNOWN"
|
||||
#endif
|
||||
|
||||
#include <exception>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
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
|
@ -2,11 +2,13 @@
|
||||
#define YERBACON_LEX_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include "Yerbacon.hpp"
|
||||
#include <ostream>
|
||||
|
||||
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,
|
||||
|
@ -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<ParseComponent> 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<ParseComponent>& 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<ParseComponent>& 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
|
@ -4,18 +4,39 @@
|
||||
#include <string>
|
||||
#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<tok>& 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user