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 "../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 {
|
||||||
|
@ -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
|
@ -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,
|
||||||
|
@ -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
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user