Implements very simple REPL, fixes several issues found with it.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2021-01-02 17:41:53 +01:00
parent de15173b0b
commit 9109b7513a
8 changed files with 317 additions and 11 deletions

View File

@@ -35,21 +35,26 @@ namespace MalachScript {
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
static int constexpr CalcLength(const char8_t* str) { return *str ? 1 + CalcLength(str + 1) : 0; }
static std::u8string empty;
class Identifier {
std::u8string_view _str;
const char8_t* _str;
size_t _length;
uint32_t _hash;
public:
Identifier() : _str(empty), _hash(0) {}
constexpr Identifier(const char8_t* c) : _str(c), _hash(Hash(c)) {}
Identifier(const std::u8string_view& c) : _str(c), _hash(Hash(c)) {}
Identifier(const std::u8string_view& c, uint32_t hash) : _str(c), _hash(hash) {}
Identifier() : _str(nullptr), _length(0), _hash(0) {}
constexpr Identifier(const char8_t* c) : _str(c), _length(CalcLength(c)), _hash(Hash(c)) {}
constexpr Identifier(const char8_t* c, size_t length, uint32_t hash) : _str(c), _length(length), _hash(hash) {}
[[nodiscard]] constexpr inline uint32_t GetHash() const noexcept { return _hash; }
[[nodiscard]] constexpr inline const std::u8string_view& GetString() const noexcept { return _str; }
[[nodiscard]] constexpr inline std::u8string_view GetString() const noexcept {
return std::u8string_view(_str, _length);
}
[[nodiscard]] constexpr inline size_t GetLength() const noexcept { return _length; }
constexpr inline static uint32_t Hash(const std::u8string_view& sv) {
uint32_t crc = 0xffffffff;
@@ -59,6 +64,11 @@ namespace MalachScript {
return crc ^ 0xffffffff;
}
friend std::ostream& operator<<(std::ostream& out, const Identifier& c) {
out << std::string((const char*)c._str, c._length);
return out;
}
private:
};

View File

@@ -12,6 +12,7 @@ namespace MalachScript::Diagnostics {
};
class DiagnosticTypeHelper {
public:
static std::string ToEnglishString(DiagnosticType type) {
switch (type) {
case DiagnosticType::UnknownToken: return "Unknown token";

View File

@@ -599,7 +599,7 @@ namespace MalachScript::Parser {
case Identifier::Hash(u8"xor"):
return Create<LexTokenImpl<LexTokenKind::XorKeyword>>(TextSpan(start, _position));
default: return Create<IdentifierToken>(TextSpan(start, _position), Identifier(str, hash));
default: return Create<IdentifierToken>(TextSpan(start, _position), Identifier(str.data(), offset, hash));
}
}
bool Lexer::IsAlphaNumericalOrUnderscore(char8_t c) {

View File

@@ -49,6 +49,7 @@ namespace MalachScript::Parser {
ParseFunc(statement, currentToken, log) || ParseNamespace(statement, currentToken, log);
if (!result) {
// TODO: Log error
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
PROGRESS_TOKEN(currentToken);
continue;
}
@@ -82,6 +83,7 @@ namespace MalachScript::Parser {
Identifier identifier;
if (!ParseIdentifier(identifier, current)) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
PROGRESS_TOKEN(current);
std::vector<Identifier> inherits;
@@ -97,18 +99,21 @@ namespace MalachScript::Parser {
Identifier id;
if (!ParseIdentifier(id, current)) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
inherits.push_back(id);
while (current->GetKind() == LexTokenKind::CommaSymbol) {
PROGRESS_TOKEN(current);
if (!ParseIdentifier(id, current)) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
inherits.push_back(id);
PROGRESS_TOKEN(current);
}
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
[[fallthrough]];
// Intentionally don't break so we continue into the inner body statement.
@@ -132,7 +137,7 @@ namespace MalachScript::Parser {
}
break;
}
default: throw;
default: return false;
}
out = new ParsedClassStatement(TextSpan(start, current->GetSpan().GetEnd()), classAttr, identifier, inherits,
body);
@@ -239,6 +244,7 @@ namespace MalachScript::Parser {
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
if (!ParseStatBlock(statblock, current, log)) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
} else {
PROGRESS_TOKEN(current);
@@ -367,6 +373,7 @@ namespace MalachScript::Parser {
PROGRESS_TOKEN(currentToken);
if (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
PROGRESS_TOKEN(currentToken);
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters);
@@ -385,9 +392,13 @@ namespace MalachScript::Parser {
if (!ParseType(typeStatement, currentToken, log)) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
ParseTypeMod(typeMod, currentToken, log);
ParseIdentifier(identifier, currentToken);
if (!ParseIdentifier(identifier, currentToken)) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
PROGRESS_TOKEN(currentToken);
// TODO: Default expression
@@ -403,10 +414,12 @@ namespace MalachScript::Parser {
while (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
if (currentToken->GetKind() == LexTokenKind::EndOfFile) {
break;
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
if (currentToken->GetKind() == LexTokenKind::SemicolonSymbol) {
break;
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
PROGRESS_TOKEN(currentToken);
}

View File

@@ -1,6 +1,7 @@
#ifndef MALACHSCRIPT_PARSEDSTATEMENT_HPP
#define MALACHSCRIPT_PARSEDSTATEMENT_HPP
#include <sstream>
#include <utility>
#include <vector>
#include "../../CoreData/AccessModifier.hpp"
@@ -18,6 +19,13 @@ namespace MalachScript::Parser {
virtual ~ParsedStatement() = default;
[[nodiscard]] virtual ParsedStatementKind GetKind() const noexcept = 0;
[[nodiscard]] inline const TextSpan& GetSpan() const noexcept { return _span; }
virtual void Stringify(std::stringstream& stream, uint8_t indents) const {
for (uint8_t i = 0; i < indents; i++) {
stream << "\t";
}
stream << ParsedStatementKindHelper::ToString(GetKind());
}
};
template <ParsedStatementKind kind> class ParsedStatementImpl : public ParsedStatement {
@@ -39,6 +47,15 @@ namespace MalachScript::Parser {
[[nodiscard]] inline const std::vector<std::unique_ptr<const ParsedStatement>>& GetStatements() const noexcept {
return _statements;
}
void Stringify(std::stringstream& stream, uint8_t indents) const override {
ParsedStatement::Stringify(stream, indents);
stream << std::to_string(GetStatements().size());
stream << std::endl;
for (const auto& s : GetStatements()) {
s->Stringify(stream, indents + 1);
}
}
};
class ParsedClassStatement : public ParsedStatementImpl<ParsedStatementKind::Class> {
@@ -58,6 +75,15 @@ namespace MalachScript::Parser {
return _body;
}
void Stringify(std::stringstream& stream, uint8_t indents) const override {
ParsedStatement::Stringify(stream, indents);
stream << " " << _identifier;
stream << std::endl;
for (const auto& s : GetBody()) {
s->Stringify(stream, indents + 1);
}
}
private:
ClassAttr _classAttr;
Identifier _identifier;
@@ -108,6 +134,23 @@ namespace MalachScript::Parser {
[[nodiscard]] inline bool IsArray() const noexcept { return _isArray; }
[[nodiscard]] inline bool IsHandle() const noexcept { return _isHandle; }
[[nodiscard]] inline const ScopedIdentifier& GetScopedIdentifier() const noexcept { return _scopedIdentifier; }
void Stringify(std::stringstream& stream, uint8_t) const override {
if (_isConst) {
stream << "const ";
}
for (auto identifier : _scopedIdentifier.GetScope()) {
stream << identifier;
stream << "::";
}
stream << _scopedIdentifier.GetIdentifier();
if (_isArray) {
stream << "[]";
}
if (_isHandle) {
stream << "&";
}
}
};
class ParsedParamListStatement : public ParsedStatementImpl<ParsedStatementKind::ParamList> {
@@ -160,6 +203,15 @@ namespace MalachScript::Parser {
[[nodiscard]] const std::vector<std::unique_ptr<const ParsedParameter>>& GetParameters() const noexcept {
return _parameters;
}
void Stringify(std::stringstream& stream, uint8_t indents) const override {
stream << "(";
for (auto& param : GetParameters()) {
param->GetTypeStatement()->Stringify(stream, indents);
stream << " " << param->GetIdentifier();
}
stream << ")";
}
};
class ParsedFuncStatement : public ParsedStatementImpl<ParsedStatementKind::Func> {
@@ -200,6 +252,14 @@ namespace MalachScript::Parser {
[[nodiscard]] inline const std::unique_ptr<const ParsedStatement>& GetStatBlock() const noexcept {
return _statBlock;
}
void Stringify(std::stringstream& stream, uint8_t indents) const override {
ParsedStatement::Stringify(stream, indents);
stream << " " << _identifier;
GetParamList()->Stringify(stream, 0);
stream << std::endl;
GetStatBlock()->Stringify(stream, indents + 1);
}
};
class ParsedVirtPropStatement : public ParsedStatementImpl<ParsedStatementKind::VirtProp> {

View File

@@ -31,6 +31,41 @@ namespace MalachScript::Parser {
Switch,
Case,
};
class ParsedStatementKindHelper {
public:
static std::string_view ToString(ParsedStatementKind kind) {
switch (kind) {
case ParsedStatementKind::Unknown: return "Unknown";
case ParsedStatementKind::Script: return "Script";
case ParsedStatementKind::Class: return "Class";
case ParsedStatementKind::TypeDef: return "TypeDef";
case ParsedStatementKind::Namespace: return "Namespace";
case ParsedStatementKind::Type: return "Type";
case ParsedStatementKind::ParamList: return "ParamList";
case ParsedStatementKind::Func: return "Func";
case ParsedStatementKind::VirtProp: return "VirtProp";
case ParsedStatementKind::StatBlock: return "StatBlock";
case ParsedStatementKind::If: return "If";
case ParsedStatementKind::Assign: return "Assign";
case ParsedStatementKind::BinaryExpression: return "BinaryExpression";
case ParsedStatementKind::Void: return "Void";
case ParsedStatementKind::Literal: return "Literal";
case ParsedStatementKind::Return: return "Return";
case ParsedStatementKind::VarAccess: return "VarAccess";
case ParsedStatementKind::Increment: return "Increment";
case ParsedStatementKind::Decrement: return "Decrement";
case ParsedStatementKind::Continue: return "Continue";
case ParsedStatementKind::Break: return "Break";
case ParsedStatementKind::For: return "For";
case ParsedStatementKind::While: return "While";
case ParsedStatementKind::DoWhile: return "DoWhile";
case ParsedStatementKind::Try: return "Try";
case ParsedStatementKind::Switch: return "Switch";
case ParsedStatementKind::Case: return "Case";
}
}
};
}
#endif // MALACHSCRIPT_PARSEDSTATEMENTKIND_HPP