Initial work on type registration in the binder.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
da82819fff
commit
093ffde6bc
|
@ -19,7 +19,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|||
add_link_options(-fuse-ld=lld)
|
||||
endif ()
|
||||
|
||||
file(GLOB_RECURSE SRC_FILES "src/*.cpp" "src/*.hpp")
|
||||
file(GLOB_RECURSE SRC_FILES "src/*.cpp")
|
||||
add_library(MalachScript SHARED ${SRC_FILES})
|
||||
|
||||
set(LINKS)
|
||||
|
|
|
@ -9,14 +9,14 @@ namespace MalachScriptRepl {
|
|||
private:
|
||||
WINDOW* _window;
|
||||
|
||||
std::vector<std::u8string> _lines = {u8""};
|
||||
std::vector<std::string> _lines = {""};
|
||||
int _row = 0;
|
||||
int _col = 0;
|
||||
int _rightPos = 0;
|
||||
int _scroll = 0;
|
||||
int _lineCount;
|
||||
|
||||
std::function<void(const std::vector<std::u8string>&)> _onChange;
|
||||
std::function<void(const std::vector<std::string>&)> _onChange;
|
||||
const MalachScript::Diagnostics::Diagnostic* _diag;
|
||||
|
||||
public:
|
||||
|
@ -26,7 +26,7 @@ namespace MalachScriptRepl {
|
|||
_lineCount = height;
|
||||
}
|
||||
|
||||
inline void RegisterOnChange(std::function<void(const std::vector<std::u8string>&)> listener) {
|
||||
inline void RegisterOnChange(std::function<void(const std::vector<std::string>&)> listener) {
|
||||
_onChange = listener;
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ namespace MalachScriptRepl {
|
|||
}
|
||||
|
||||
inline void Return() {
|
||||
_lines.insert(_lines.begin() + _row + _scroll + 1, u8"");
|
||||
_lines.insert(_lines.begin() + _row + _scroll + 1, "");
|
||||
if (_row >= _lineCount - 1) {
|
||||
ScrollDown();
|
||||
} else {
|
||||
|
@ -119,10 +119,10 @@ namespace MalachScriptRepl {
|
|||
wclrtoeol(_window);
|
||||
auto& line = _lines[_row + _scroll];
|
||||
if ((int)line.length() <= _col) {
|
||||
line += u8" ";
|
||||
line += " ";
|
||||
} else {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
line.insert(line.begin() + _col, u8' ');
|
||||
line.insert(line.begin() + _col, ' ');
|
||||
}
|
||||
}
|
||||
waddstr(_window, (char*)line.c_str());
|
||||
|
@ -148,7 +148,7 @@ namespace MalachScriptRepl {
|
|||
wmove(_window, _row, 0);
|
||||
auto& line = _lines[_row + _scroll];
|
||||
if ((int)line.length() <= _col) {
|
||||
line += (char8_t)c;
|
||||
line += (char)c;
|
||||
} else {
|
||||
line.insert(line.begin() + _col, c);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ namespace MalachScriptRepl {
|
|||
}
|
||||
|
||||
inline void ResetText() {
|
||||
std::u8string script;
|
||||
std::string script;
|
||||
for (size_t i = 0; i < _lines.size(); i++) {
|
||||
script += _lines[i];
|
||||
if (i != _lines.size() - 1) {
|
||||
|
@ -196,11 +196,11 @@ namespace MalachScriptRepl {
|
|||
wmove(_window, _row, _col);
|
||||
}
|
||||
|
||||
inline void SetScriptWithDiagnostics(std::u8string& script, const MalachScript::Diagnostics::Diagnostic* diag) {
|
||||
inline void SetScriptWithDiagnostics(std::string& script, const MalachScript::Diagnostics::Diagnostic* diag) {
|
||||
_diag = diag;
|
||||
auto yx = GetCursorPosition();
|
||||
Clear();
|
||||
script += u8" ";
|
||||
script += " ";
|
||||
|
||||
size_t linenum = 0;
|
||||
size_t index = 0;
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
#include "../src/Parser/Statements/ParsedStatementStringifier.hpp"
|
||||
#include "InputWindow.hpp"
|
||||
|
||||
void ParseAndUpdate(const std::vector<std::u8string>& lines, WINDOW* diagnosticsWindow, WINDOW* parsedWindow,
|
||||
void ParseAndUpdate(const std::vector<std::string>& lines, WINDOW* diagnosticsWindow, WINDOW* parsedWindow,
|
||||
MalachScriptRepl::InputWindow& inputWindow) {
|
||||
std::u8string script;
|
||||
std::string script;
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
script += lines[i];
|
||||
if (i != lines.size() - 1) {
|
||||
|
@ -23,9 +23,9 @@ void ParseAndUpdate(const std::vector<std::u8string>& lines, WINDOW* diagnostics
|
|||
outfile.close();
|
||||
|
||||
auto logger = MalachScript::Diagnostics::Logger();
|
||||
auto lexer = MalachScript::Parser::Lexer(u8"diag", script, &logger);
|
||||
auto lexer = MalachScript::Parser::Lexer("diag", script, &logger);
|
||||
const auto* firstToken = lexer.Lex();
|
||||
const auto* parsedResult = MalachScript::Parser::Parser::Parse(firstToken, u8"diag", &logger);
|
||||
const auto* parsedResult = MalachScript::Parser::Parser::Parse(firstToken, "diag", &logger);
|
||||
|
||||
const MalachScript::Diagnostics::Diagnostic* diag = nullptr;
|
||||
wclear(diagnosticsWindow);
|
||||
|
@ -96,7 +96,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[]) {
|
|||
|
||||
auto inputWindow = MalachScriptRepl::InputWindow(inputFieldSize, maxX - 3, 1, 2);
|
||||
inputWindow.RegisterOnChange(
|
||||
[diagnosticsWindow, parsedResultWindow, &inputWindow](const std::vector<std::u8string>& lines) {
|
||||
[diagnosticsWindow, parsedResultWindow, &inputWindow](const std::vector<std::string>& lines) {
|
||||
ParseAndUpdate(lines, diagnosticsWindow, parsedResultWindow, inputWindow);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
#include "Binder.hpp"
|
||||
#include "../CoreData/PrimitiveTypes.hpp"
|
||||
#include "../Diagnostics/Logger.hpp"
|
||||
using namespace MalachScript::Parser;
|
||||
using namespace MalachScript::Diagnostics;
|
||||
|
||||
namespace MalachScript::Binder {
|
||||
void Binder::Bind(BoundNamespace* ns, const std::vector<const MalachScript::Parser::ParsedStatement*>& statements,
|
||||
const Binder::log_func& log) {
|
||||
for (const auto* s : statements) {
|
||||
TypeRegistrationFirstPass(ns, s, {}, log);
|
||||
}
|
||||
for (const auto* s : statements) {
|
||||
TypeRegistrationSecondPass(ns, s, {}, log);
|
||||
}
|
||||
for (const auto* s : statements) {
|
||||
TypeRegistrationThirdPass(ns, s, {}, log);
|
||||
}
|
||||
FinaliseTypes(ns, log);
|
||||
}
|
||||
|
||||
inline static std::optional<const BoundType*> ResolveType(BoundNamespace* ns, const Identifier& identifier) {
|
||||
switch (identifier) {
|
||||
case "int"_id: return MalachScript::PrimitiveTypes::IntType();
|
||||
case "int8"_id: return MalachScript::PrimitiveTypes::Int8Type();
|
||||
case "int16"_id: return MalachScript::PrimitiveTypes::Int16Type();
|
||||
case "int32"_id: return MalachScript::PrimitiveTypes::Int32Type();
|
||||
case "int64"_id: return MalachScript::PrimitiveTypes::Int64Type();
|
||||
|
||||
case "uint"_id: return MalachScript::PrimitiveTypes::UintType();
|
||||
case "uint8"_id: return MalachScript::PrimitiveTypes::Uint8Type();
|
||||
case "uint16"_id: return MalachScript::PrimitiveTypes::Uint16Type();
|
||||
case "uint32"_id: return MalachScript::PrimitiveTypes::Uint32Type();
|
||||
case "uint64"_id: return MalachScript::PrimitiveTypes::Uint64Type();
|
||||
|
||||
case "float"_id: return MalachScript::PrimitiveTypes::FloatType();
|
||||
case "double"_id: return MalachScript::PrimitiveTypes::DoubleType();
|
||||
|
||||
case "bool"_id: return MalachScript::PrimitiveTypes::BoolType();
|
||||
}
|
||||
return ns->ResolveType(identifier);
|
||||
}
|
||||
|
||||
void Binder::TypeRegistrationFirstPass(BoundNamespace* ns, const ParsedStatement* statement,
|
||||
std::optional<BoundType*> activeType, const log_func& log) {
|
||||
switch (statement->GetKind()) {
|
||||
case Parser::ParsedStatementKind::Script: {
|
||||
const auto* s = static_cast<const ParsedScriptStatement*>(statement);
|
||||
for (const auto& child : s->GetStatements()) {
|
||||
TypeRegistrationFirstPass(ns, child.get(), activeType, log);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Parser::ParsedStatementKind::Class: {
|
||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||
auto identifier = s->GetIdentifier();
|
||||
if (activeType.has_value()) {
|
||||
}
|
||||
auto* type = new BoundType(s->GetClassAttr());
|
||||
if (activeType.has_value()) {
|
||||
activeType.value()->RegisterType(identifier, type);
|
||||
} else {
|
||||
ns->RegisterType(identifier, type);
|
||||
}
|
||||
for (const auto& child : s->GetBody()) {
|
||||
TypeRegistrationFirstPass(ns, child.get(), type, log);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Parser::ParsedStatementKind::Namespace: {
|
||||
const auto* s = static_cast<const ParsedNamespaceStatement*>(statement);
|
||||
auto identifier = s->GetIdentifier();
|
||||
auto* innerNamespace = new BoundNamespace();
|
||||
ns->RegisterNamespace(identifier, innerNamespace);
|
||||
TypeRegistrationFirstPass(innerNamespace, s->GetScript().get(), activeType, log);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
void Binder::TypeRegistrationSecondPass(BoundNamespace* ns, const ParsedStatement* statement,
|
||||
std::optional<BoundType*> activeType, const log_func& log) {
|
||||
switch (statement->GetKind()) {
|
||||
case ParsedStatementKind::Script: {
|
||||
const auto* s = static_cast<const ParsedScriptStatement*>(statement);
|
||||
for (const auto& child : s->GetStatements()) {
|
||||
TypeRegistrationSecondPass(ns, child.get(), activeType, log);
|
||||
}
|
||||
break;
|
||||
};
|
||||
case ParsedStatementKind::Class: {
|
||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||
auto type = ns->ResolveType(s->GetIdentifier());
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
for (const auto& inherits : s->GetInherits()) {
|
||||
auto inheritType = ResolveType(ns, inherits);
|
||||
if (!inheritType.has_value()) {
|
||||
log(DiagnosticLevel::Error, DiagnosticType::UnknownType, s->GetSpan(),
|
||||
{inherits.GetStdString()});
|
||||
} else {
|
||||
type.value()->AddInheritType(inheritType.value());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& child : s->GetBody()) {
|
||||
TypeRegistrationSecondPass(ns, child.get(), type.value(), log);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParsedStatementKind::TypeDef: {
|
||||
const auto* s = static_cast<const ParsedTypeDefStatement*>(statement);
|
||||
auto defineTo = s->GetDefineTo();
|
||||
auto defineFrom = s->GetDefineFrom();
|
||||
auto defineFromType = ResolveType(ns, defineFrom);
|
||||
if (!defineFromType.has_value()) {
|
||||
log(DiagnosticLevel::Error, DiagnosticType::UnknownType, s->GetSpan(), {defineFrom.GetStdString()});
|
||||
} else {
|
||||
if (activeType.has_value()) {
|
||||
activeType.value()->RegisterType(defineTo, defineFromType.value());
|
||||
} else {
|
||||
ns->RegisterType(defineTo, defineFromType.value());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParsedStatementKind::Namespace: {
|
||||
const auto* s = static_cast<const ParsedNamespaceStatement*>(statement);
|
||||
auto identifier = s->GetIdentifier();
|
||||
auto innerNamespace = ns->ResolveNamespace(identifier);
|
||||
if (!innerNamespace.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
TypeRegistrationSecondPass(innerNamespace.value(), s->GetScript().get(), activeType, log);
|
||||
break;
|
||||
};
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
void Binder::TypeRegistrationThirdPass(BoundNamespace* ns, const MalachScript::Parser::ParsedStatement* statement,
|
||||
std::optional<BoundType*> activeType, const Binder::log_func& log) {
|
||||
switch (statement->GetKind()) {
|
||||
case ParsedStatementKind::Script: {
|
||||
const auto* s = static_cast<const ParsedScriptStatement*>(statement);
|
||||
for (const auto& child : s->GetStatements()) {
|
||||
TypeRegistrationThirdPass(ns, child.get(), activeType, log);
|
||||
}
|
||||
break;
|
||||
};
|
||||
case ParsedStatementKind::Class: {
|
||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||
auto type = ns->ResolveType(s->GetIdentifier());
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
for (const auto& child : s->GetBody()) {
|
||||
TypeRegistrationThirdPass(ns, child.get(), type.value(), log);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParsedStatementKind::Namespace: {
|
||||
const auto* s = static_cast<const ParsedNamespaceStatement*>(statement);
|
||||
auto identifier = s->GetIdentifier();
|
||||
auto innerNamespace = ns->ResolveNamespace(identifier);
|
||||
if (!innerNamespace.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
TypeRegistrationThirdPass(innerNamespace.value(), s->GetScript().get(), activeType, log);
|
||||
break;
|
||||
};
|
||||
case ParsedStatementKind::Var: {
|
||||
const auto* var = static_cast<const ParsedVarStatement*>(statement);
|
||||
const auto& typeStatement = var->GetTypeStatement();
|
||||
// FIXME: Resolve namespace of scoped identifier
|
||||
auto type = ResolveType(ns, typeStatement->GetScopedIdentifier().GetIdentifier());
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
if (activeType.has_value()) {
|
||||
activeType.value()->AddField(var->GetIdentifier(),
|
||||
new BoundVariable(type.value(), var->GetAccess()));
|
||||
} else {
|
||||
ns->AddVariable(var->GetIdentifier(), new BoundVariable(type.value(), var->GetAccess()));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FinaliseNamespace(BoundNamespace* ns, const Binder::log_func& log) {
|
||||
for (const auto& t : ns->GetTypes()) {
|
||||
t.second->Finalise();
|
||||
}
|
||||
for (const auto& n : ns->GetNamespaces()) {
|
||||
FinaliseNamespace(n.second, log);
|
||||
}
|
||||
}
|
||||
|
||||
void Binder::FinaliseTypes(BoundNamespace* ns, const Binder::log_func& log) { FinaliseNamespace(ns, log); }
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef MALACHSCRIPT_BINDER_HPP
|
||||
#define MALACHSCRIPT_BINDER_HPP
|
||||
|
||||
#include <functional>
|
||||
#include "../Diagnostics/Logger.hpp"
|
||||
#include "../Parser/Statements/ParsedStatement.hpp"
|
||||
#include "BoundNamespace.hpp"
|
||||
|
||||
namespace MalachScript::Binder {
|
||||
class Binder {
|
||||
public:
|
||||
using log_func = const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType,
|
||||
const TextSpan&, const std::vector<std::string>&)>;
|
||||
|
||||
static void Bind(BoundNamespace* ns,
|
||||
const std::vector<const MalachScript::Parser::ParsedStatement*>& statements,
|
||||
const log_func& log);
|
||||
|
||||
private:
|
||||
// Register all types and namespaces
|
||||
static void TypeRegistrationFirstPass(BoundNamespace* ns,
|
||||
const MalachScript::Parser::ParsedStatement* statement,
|
||||
std::optional<BoundType*> activeType, const log_func& log);
|
||||
// Register typedefs and type inheritance
|
||||
static void TypeRegistrationSecondPass(BoundNamespace* ns,
|
||||
const MalachScript::Parser::ParsedStatement* statement,
|
||||
std::optional<BoundType*> activeType, const log_func& log);
|
||||
// Register variables, fields, etc
|
||||
static void TypeRegistrationThirdPass(BoundNamespace* ns,
|
||||
const MalachScript::Parser::ParsedStatement* statement,
|
||||
std::optional<BoundType*> activeType, const log_func& log);
|
||||
// Finalise types, calculating size.
|
||||
static void FinaliseTypes(BoundNamespace* ns, const log_func& log);
|
||||
};
|
||||
}
|
||||
#endif // MALACHSCRIPT_BINDER_HPP
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef MALACHSCRIPT_BOUNDNAMESPACE_HPP
|
||||
#define MALACHSCRIPT_BOUNDNAMESPACE_HPP
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include "../CoreData/Identifier.hpp"
|
||||
#include "BoundType.hpp"
|
||||
#include "BoundVariable.hpp"
|
||||
|
||||
namespace MalachScript::Binder {
|
||||
class BoundNamespace {
|
||||
public:
|
||||
inline void RegisterNamespace(const Identifier& identifier, BoundNamespace* ns) {
|
||||
_namespaces[identifier] = ns;
|
||||
}
|
||||
|
||||
inline void RegisterType(const Identifier& identifier, BoundType* type) { _types[identifier] = type; }
|
||||
inline void RegisterType(const Identifier& identifier, const BoundType* type) {
|
||||
_types[identifier] = const_cast<BoundType*>(type);
|
||||
}
|
||||
inline void AddVariable(const Identifier& identifier, BoundVariable* var) { _variables[identifier] = var; }
|
||||
|
||||
inline std::optional<BoundType*> ResolveType(const Identifier& identifier) const noexcept {
|
||||
auto find = _types.find(identifier);
|
||||
if (find == _types.end()) {
|
||||
return {};
|
||||
}
|
||||
return find->second;
|
||||
}
|
||||
inline std::optional<BoundNamespace*> ResolveNamespace(const Identifier& identifier) const noexcept {
|
||||
auto find = _namespaces.find(identifier);
|
||||
if (find == _namespaces.end()) {
|
||||
return {};
|
||||
}
|
||||
return find->second;
|
||||
}
|
||||
|
||||
inline const std::unordered_map<Identifier, BoundNamespace*>& GetNamespaces() const noexcept {
|
||||
return _namespaces;
|
||||
}
|
||||
inline const std::unordered_map<Identifier, BoundType*>& GetTypes() const noexcept { return _types; }
|
||||
|
||||
private:
|
||||
std::unordered_map<Identifier, BoundNamespace*> _namespaces;
|
||||
std::unordered_map<Identifier, BoundType*> _types;
|
||||
std::unordered_map<Identifier, BoundVariable*> _variables;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_BOUNDNAMESPACE_HPP
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef MALACHSCRIPT_BOUNDTYPE_HPP
|
||||
#define MALACHSCRIPT_BOUNDTYPE_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include "BoundVariable.hpp"
|
||||
|
||||
namespace MalachScript::Binder {
|
||||
class BoundType {
|
||||
public:
|
||||
BoundType(ClassAttr classAttr) : _classAttr(classAttr) {}
|
||||
BoundType(ClassAttr classAttr, size_t size) : _classAttr(classAttr), _size(size), _inherits(0) {}
|
||||
|
||||
inline void Finalise() noexcept {
|
||||
_initialised = true;
|
||||
// TODO: Calculate size
|
||||
}
|
||||
[[nodiscard]] inline size_t GetSize() const noexcept { return _size; }
|
||||
[[nodiscard]] inline ClassAttr GetAttributes() const noexcept { return _classAttr; }
|
||||
|
||||
inline void AddInheritType(const BoundType* type) { _inherits.push_back(type); }
|
||||
inline void AddField(const Identifier& identifier, BoundVariable* var) {
|
||||
_fields.push_back(var);
|
||||
_fieldsLookup[identifier] = var;
|
||||
}
|
||||
|
||||
inline void RegisterType(const Identifier& identifier, const BoundType* type) {
|
||||
_types[identifier] = const_cast<BoundType*>(type);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _initialised = false;
|
||||
ClassAttr _classAttr;
|
||||
size_t _size = 0;
|
||||
std::vector<const BoundType*> _inherits;
|
||||
std::vector<BoundVariable*> _fields;
|
||||
std::unordered_map<Identifier, BoundVariable*> _fieldsLookup;
|
||||
// TODO: functions
|
||||
|
||||
std::unordered_map<Identifier, BoundType*> _types;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_BOUNDTYPE_HPP
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef MALACHSCRIPT_BOUNDVARIABLE_HPP
|
||||
#define MALACHSCRIPT_BOUNDVARIABLE_HPP
|
||||
|
||||
namespace MalachScript::Binder {
|
||||
class BoundType;
|
||||
|
||||
class BoundVariable {
|
||||
public:
|
||||
BoundVariable(const BoundType* type, AccessModifier accessModifier)
|
||||
: _type(type), _accessModifier(accessModifier) {}
|
||||
|
||||
[[nodiscard]] inline const BoundType* GetType() const noexcept { return _type; }
|
||||
[[nodiscard]] inline AccessModifier GetAccess() const noexcept { return _accessModifier; }
|
||||
|
||||
private:
|
||||
const BoundType* _type;
|
||||
AccessModifier _accessModifier;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_BOUNDVARIABLE_HPP
|
|
@ -2,7 +2,10 @@
|
|||
#define MALACHSCRIPT_IDENTIFIER_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace MalachScript {
|
||||
|
||||
constexpr static uint32_t crc_table[256] = {
|
||||
|
@ -35,28 +38,30 @@ 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 int constexpr CalcLength(const char* str) { return *str ? 1 + CalcLength(str + 1) : 0; }
|
||||
|
||||
static std::u8string empty;
|
||||
static std::string empty;
|
||||
|
||||
class Identifier {
|
||||
const char8_t* _str;
|
||||
const char* _str;
|
||||
size_t _length;
|
||||
uint32_t _hash;
|
||||
|
||||
public:
|
||||
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) {}
|
||||
constexpr Identifier(const char* c) : _str(c), _length(CalcLength(c)), _hash(Hash(c)) {}
|
||||
constexpr Identifier(const char* c, size_t length) : _str(c), _length(length), _hash(Hash(c)) {}
|
||||
constexpr Identifier(const char* 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 std::u8string_view GetString() const noexcept {
|
||||
return std::u8string_view(_str, _length);
|
||||
[[nodiscard]] constexpr inline std::string_view GetString() const noexcept {
|
||||
return std::string_view(_str, _length);
|
||||
}
|
||||
[[nodiscard]] inline std::string GetStdString() const noexcept { return std::string((char*)_str, _length); }
|
||||
|
||||
[[nodiscard]] constexpr inline size_t GetLength() const noexcept { return _length; }
|
||||
|
||||
constexpr inline static uint32_t Hash(const std::u8string_view& sv) {
|
||||
constexpr inline static uint32_t Hash(const std::string_view& sv) {
|
||||
uint32_t crc = 0xffffffff;
|
||||
for (auto c : sv) {
|
||||
crc = (crc >> 8) ^ crc_table[(crc ^ c) & 0xff];
|
||||
|
@ -64,6 +69,9 @@ namespace MalachScript {
|
|||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline constexpr std::size_t operator()() const noexcept { return _hash; }
|
||||
[[nodiscard]] inline constexpr operator uint32_t() const noexcept { return _hash; }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const Identifier& c) {
|
||||
out << std::string((const char*)c._str, c._length);
|
||||
return out;
|
||||
|
@ -86,4 +94,18 @@ namespace MalachScript {
|
|||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
/// @brief Helper class for getting the hash of a string view literal.
|
||||
template <> struct hash<MalachScript::Identifier> {
|
||||
/// @brief Returns the hash of a stringview.
|
||||
/// @param s a StringView.
|
||||
/// @return The hash of the StringView.
|
||||
constexpr std::size_t operator()(MalachScript::Identifier const& s) const noexcept { return s.GetHash(); }
|
||||
};
|
||||
}
|
||||
|
||||
inline constexpr MalachScript::Identifier operator"" _id(const char* c, size_t l) {
|
||||
return MalachScript::Identifier(c, l);
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_IDENTIFIER_HPP
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define MALACHSCRIPT_PRIMITIVETYPES_HPP
|
||||
|
||||
#include <string>
|
||||
#include "../Binder/BoundType.hpp"
|
||||
#include "Identifier.hpp"
|
||||
|
||||
#if !__cpp_constinit
|
||||
|
@ -9,22 +10,34 @@
|
|||
#endif
|
||||
|
||||
namespace MalachScript {
|
||||
static constinit Identifier _voidName = u8"void";
|
||||
static constinit Identifier _intName = u8"int";
|
||||
static constinit Identifier _int8Name = u8"int8";
|
||||
static constinit Identifier _int16Name = u8"int16";
|
||||
static constinit Identifier _int32Name = u8"int32";
|
||||
static constinit Identifier _int64Name = u8"int64";
|
||||
static constinit Identifier _uintName = u8"uint";
|
||||
static constinit Identifier _uint8Name = u8"uint8";
|
||||
static constinit Identifier _uint16Name = u8"uint16";
|
||||
static constinit Identifier _uint32Name = u8"uint32";
|
||||
static constinit Identifier _uint64Name = u8"uint64";
|
||||
static constinit Identifier _floatName = u8"float";
|
||||
static constinit Identifier _doubleName = u8"double";
|
||||
static constinit Identifier _boolName = u8"bool";
|
||||
static constinit Identifier _voidName = "void";
|
||||
static constinit Identifier _intName = "int";
|
||||
static constinit Identifier _int8Name = "int8";
|
||||
static constinit Identifier _int16Name = "int16";
|
||||
static constinit Identifier _int32Name = "int32";
|
||||
static constinit Identifier _int64Name = "int64";
|
||||
static constinit Identifier _uintName = "uint";
|
||||
static constinit Identifier _uint8Name = "uint8";
|
||||
static constinit Identifier _uint16Name = "uint16";
|
||||
static constinit Identifier _uint32Name = "uint32";
|
||||
static constinit Identifier _uint64Name = "uint64";
|
||||
static constinit Identifier _floatName = "float";
|
||||
static constinit Identifier _doubleName = "double";
|
||||
static constinit Identifier _boolName = "bool";
|
||||
|
||||
static constinit Identifier _autoName = u8"auto";
|
||||
static constinit Identifier _autoName = "auto";
|
||||
|
||||
static Binder::BoundType _int8Type = Binder::BoundType(ClassAttr::None, sizeof(int8_t));
|
||||
static Binder::BoundType _int16Type = Binder::BoundType(ClassAttr::None, sizeof(int16_t));
|
||||
static Binder::BoundType _int32Type = Binder::BoundType(ClassAttr::None, sizeof(int32_t));
|
||||
static Binder::BoundType _int64Type = Binder::BoundType(ClassAttr::None, sizeof(int64_t));
|
||||
static Binder::BoundType _uint8Type = Binder::BoundType(ClassAttr::None, sizeof(uint8_t));
|
||||
static Binder::BoundType _uint16Type = Binder::BoundType(ClassAttr::None, sizeof(uint16_t));
|
||||
static Binder::BoundType _uint32Type = Binder::BoundType(ClassAttr::None, sizeof(uint32_t));
|
||||
static Binder::BoundType _uint64Type = Binder::BoundType(ClassAttr::None, sizeof(uint64_t));
|
||||
static Binder::BoundType _floatType = Binder::BoundType(ClassAttr::None, sizeof(float));
|
||||
static Binder::BoundType _doubleType = Binder::BoundType(ClassAttr::None, sizeof(double));
|
||||
static Binder::BoundType _boolType = Binder::BoundType(ClassAttr::None, sizeof(uint8_t));
|
||||
|
||||
class PrimitiveTypes {
|
||||
public:
|
||||
|
@ -43,6 +56,20 @@ namespace MalachScript {
|
|||
constexpr static const Identifier& DoubleName() noexcept { return _doubleName; }
|
||||
constexpr static const Identifier& BoolName() noexcept { return _boolName; }
|
||||
constexpr static const Identifier& AutoName() noexcept { return _autoName; }
|
||||
|
||||
constexpr static const Binder::BoundType* IntType() noexcept { return &_int32Type; }
|
||||
constexpr static const Binder::BoundType* Int8Type() noexcept { return &_int8Type; }
|
||||
constexpr static const Binder::BoundType* Int16Type() noexcept { return &_int16Type; }
|
||||
constexpr static const Binder::BoundType* Int32Type() noexcept { return &_int32Type; }
|
||||
constexpr static const Binder::BoundType* Int64Type() noexcept { return &_int64Type; }
|
||||
constexpr static const Binder::BoundType* UintType() noexcept { return &_uint32Type; }
|
||||
constexpr static const Binder::BoundType* Uint8Type() noexcept { return &_uint8Type; }
|
||||
constexpr static const Binder::BoundType* Uint16Type() noexcept { return &_uint16Type; }
|
||||
constexpr static const Binder::BoundType* Uint32Type() noexcept { return &_uint32Type; }
|
||||
constexpr static const Binder::BoundType* Uint64Type() noexcept { return &_uint64Type; }
|
||||
constexpr static const Binder::BoundType* FloatType() noexcept { return &_floatType; }
|
||||
constexpr static const Binder::BoundType* DoubleType() noexcept { return &_doubleType; }
|
||||
constexpr static const Binder::BoundType* BoolType() noexcept { return &_boolType; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,19 +9,19 @@ namespace MalachScript::Diagnostics {
|
|||
class Diagnostic {
|
||||
DiagnosticLevel _level;
|
||||
DiagnosticType _type;
|
||||
std::u8string_view _scriptName;
|
||||
std::string_view _scriptName;
|
||||
TextSpan _span;
|
||||
std::vector<std::string> _formats;
|
||||
|
||||
public:
|
||||
inline Diagnostic(DiagnosticLevel level, DiagnosticType type, const std::u8string_view& scriptName,
|
||||
TextSpan span, const std::vector<std::string>& formats = {})
|
||||
inline Diagnostic(DiagnosticLevel level, DiagnosticType type, const std::string_view& scriptName, TextSpan span,
|
||||
const std::vector<std::string>& formats = {})
|
||||
: _level(level), _type(type), _scriptName(scriptName), _span(span), _formats(formats) {}
|
||||
|
||||
[[nodiscard]] inline DiagnosticLevel GetLevel() const noexcept { return _level; }
|
||||
[[nodiscard]] inline DiagnosticType GetType() const noexcept { return _type; }
|
||||
[[nodiscard]] inline const TextSpan& GetSpan() const noexcept { return _span; }
|
||||
[[nodiscard]] inline const std::u8string_view& GetScriptName() const noexcept { return _scriptName; }
|
||||
[[nodiscard]] inline const std::string_view& GetScriptName() const noexcept { return _scriptName; }
|
||||
[[nodiscard]] inline const std::vector<std::string>& GetFormats() const noexcept { return _formats; }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace MalachScript::Diagnostics {
|
|||
ExpectedEndOfString,
|
||||
UnexpectedToken,
|
||||
DoubleProperty,
|
||||
|
||||
UnknownType,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace MalachScript::Diagnostics {
|
|||
diag->GetFormats());
|
||||
}
|
||||
case DiagnosticType::DoubleProperty: return "Property block found twice.";
|
||||
|
||||
case DiagnosticType::UnknownType: util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
|
||||
}
|
||||
return std::to_string((uint8_t)diag->GetType());
|
||||
}
|
||||
|
|
|
@ -9,24 +9,24 @@ namespace MalachScript::Diagnostics {
|
|||
std::vector<Diagnostic> _messages;
|
||||
|
||||
public:
|
||||
inline void Log(DiagnosticLevel level, DiagnosticType type, std::u8string_view scriptName, TextSpan span,
|
||||
inline void Log(DiagnosticLevel level, DiagnosticType type, std::string_view scriptName, TextSpan span,
|
||||
const std::vector<std::string>& formats = {}) {
|
||||
_messages.emplace_back(level, type, scriptName, span, formats);
|
||||
}
|
||||
inline void LogTrace(DiagnosticType type, std::u8string_view scriptName, TextSpan span) {
|
||||
inline void LogTrace(DiagnosticType type, std::string_view scriptName, TextSpan span) {
|
||||
Log(DiagnosticLevel::Trace, type, scriptName, span);
|
||||
}
|
||||
inline void LogInfo(DiagnosticType type, std::u8string_view scriptName, TextSpan span) {
|
||||
inline void LogInfo(DiagnosticType type, std::string_view scriptName, TextSpan span) {
|
||||
Log(DiagnosticLevel::Information, type, scriptName, span);
|
||||
}
|
||||
inline void LogWarning(DiagnosticType type, std::u8string_view scriptName, TextSpan span) {
|
||||
inline void LogWarning(DiagnosticType type, std::string_view scriptName, TextSpan span) {
|
||||
Log(DiagnosticLevel::Warning, type, scriptName, span);
|
||||
}
|
||||
inline void LogError(DiagnosticType type, std::u8string_view scriptName, TextSpan span,
|
||||
inline void LogError(DiagnosticType type, std::string_view scriptName, TextSpan span,
|
||||
const std::vector<std::string>& formats = {}) {
|
||||
Log(DiagnosticLevel::Error, type, scriptName, span, formats);
|
||||
}
|
||||
inline void LogCritical(DiagnosticType type, std::u8string_view scriptName, TextSpan span) {
|
||||
inline void LogCritical(DiagnosticType type, std::string_view scriptName, TextSpan span) {
|
||||
Log(DiagnosticLevel::Critical, type, scriptName, span);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ namespace MalachScript::Parser {
|
|||
auto start = _position;
|
||||
auto c = Consume();
|
||||
switch (c) {
|
||||
case u8'\0': return Create<LexTokenImpl<LexTokenKind::EndOfFile>>(TextSpan(start + 1, start + 2));
|
||||
case u8'*': {
|
||||
case '\0': return Create<LexTokenImpl<LexTokenKind::EndOfFile>>(TextSpan(start + 1, start + 2));
|
||||
case '*': {
|
||||
auto n = Peek();
|
||||
if (n == u8'*') {
|
||||
if (n == '*') {
|
||||
Progress();
|
||||
n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// **=
|
||||
return Create<LexTokenImpl<LexTokenKind::StarStarEqualsSymbol>>(TextSpan(start, start + 3));
|
||||
|
@ -39,7 +39,7 @@ namespace MalachScript::Parser {
|
|||
// **
|
||||
return Create<LexTokenImpl<LexTokenKind::StarStarSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// *=
|
||||
return Create<LexTokenImpl<LexTokenKind::StarEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -47,30 +47,30 @@ namespace MalachScript::Parser {
|
|||
// *
|
||||
return Create<LexTokenImpl<LexTokenKind::StarSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'/':
|
||||
if (Peek() == u8'=') {
|
||||
case '/':
|
||||
if (Peek() == '=') {
|
||||
Progress();
|
||||
// /=
|
||||
return Create<LexTokenImpl<LexTokenKind::SlashEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
// /
|
||||
return Create<LexTokenImpl<LexTokenKind::SlashSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'%':
|
||||
if (Peek() == u8'=') {
|
||||
case '%':
|
||||
if (Peek() == '=') {
|
||||
Progress();
|
||||
// %=
|
||||
return Create<LexTokenImpl<LexTokenKind::PercentEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
// %
|
||||
return Create<LexTokenImpl<LexTokenKind::PercentSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'+': {
|
||||
case '+': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// +=
|
||||
return Create<LexTokenImpl<LexTokenKind::PlusEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'+') {
|
||||
if (n == '+') {
|
||||
Progress();
|
||||
// ++
|
||||
return Create<LexTokenImpl<LexTokenKind::PlusPlusSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -78,14 +78,14 @@ namespace MalachScript::Parser {
|
|||
// +
|
||||
return Create<LexTokenImpl<LexTokenKind::PlusSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'-': {
|
||||
case '-': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// -=
|
||||
return Create<LexTokenImpl<LexTokenKind::MinusEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'-') {
|
||||
if (n == '-') {
|
||||
Progress();
|
||||
// --
|
||||
return Create<LexTokenImpl<LexTokenKind::MinusMinusSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -93,16 +93,16 @@ namespace MalachScript::Parser {
|
|||
// -
|
||||
return Create<LexTokenImpl<LexTokenKind::MinusSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'<': {
|
||||
case '<': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// <=
|
||||
return Create<LexTokenImpl<LexTokenKind::LessThanEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'<') {
|
||||
if (n == '<') {
|
||||
Progress();
|
||||
if (Peek() == u8'=') {
|
||||
if (Peek() == '=') {
|
||||
Progress();
|
||||
// <<=
|
||||
return Create<LexTokenImpl<LexTokenKind::LessThanLessThanEqualsSymbol>>(
|
||||
|
@ -114,25 +114,25 @@ namespace MalachScript::Parser {
|
|||
// <
|
||||
return Create<LexTokenImpl<LexTokenKind::LessThanSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'>': {
|
||||
case '>': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// >=
|
||||
return Create<LexTokenImpl<LexTokenKind::GreaterThanEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'>') {
|
||||
if (n == '>') {
|
||||
Progress();
|
||||
n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// >>=
|
||||
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanEqualsSymbol>>(
|
||||
TextSpan(start, start + 3));
|
||||
}
|
||||
if (n == u8'>') {
|
||||
if (n == '>') {
|
||||
Progress();
|
||||
if (Peek() == u8'=') {
|
||||
if (Peek() == '=') {
|
||||
Progress();
|
||||
// >>>=
|
||||
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol>>(
|
||||
|
@ -148,10 +148,10 @@ namespace MalachScript::Parser {
|
|||
// >
|
||||
return Create<LexTokenImpl<LexTokenKind::GreaterThanSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'(': return Create<LexTokenImpl<LexTokenKind::OpenParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case u8')': return Create<LexTokenImpl<LexTokenKind::CloseParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'=': {
|
||||
if (Peek() == u8'=') {
|
||||
case '(': return Create<LexTokenImpl<LexTokenKind::OpenParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case ')': return Create<LexTokenImpl<LexTokenKind::CloseParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case '=': {
|
||||
if (Peek() == '=') {
|
||||
Progress();
|
||||
// ==
|
||||
return Create<LexTokenImpl<LexTokenKind::EqualsEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -159,14 +159,14 @@ namespace MalachScript::Parser {
|
|||
// =
|
||||
return Create<LexTokenImpl<LexTokenKind::EqualsSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'!': {
|
||||
case '!': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// !=
|
||||
return Create<LexTokenImpl<LexTokenKind::ExclamationMarkEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'i' && Peek(2) == u8's') {
|
||||
if (n == 'i' && Peek(2) == 's') {
|
||||
Progress(2);
|
||||
// !is
|
||||
return Create<LexTokenImpl<LexTokenKind::ExclamationMarkIsSymbol>>(TextSpan(start, start + 3));
|
||||
|
@ -174,9 +174,9 @@ namespace MalachScript::Parser {
|
|||
// !
|
||||
return Create<LexTokenImpl<LexTokenKind::ExclamationMarkSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'?': return Create<LexTokenImpl<LexTokenKind::QuestionMarkSymbol>>(TextSpan(start, start + 1));
|
||||
case u8':': {
|
||||
if (Peek() == u8':') {
|
||||
case '?': return Create<LexTokenImpl<LexTokenKind::QuestionMarkSymbol>>(TextSpan(start, start + 1));
|
||||
case ':': {
|
||||
if (Peek() == ':') {
|
||||
Progress();
|
||||
// ::
|
||||
return Create<LexTokenImpl<LexTokenKind::ColonColonSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -184,14 +184,14 @@ namespace MalachScript::Parser {
|
|||
// :
|
||||
return Create<LexTokenImpl<LexTokenKind::ColonSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'&': {
|
||||
case '&': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// &=
|
||||
return Create<LexTokenImpl<LexTokenKind::AmpersandEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'&') {
|
||||
if (n == '&') {
|
||||
Progress();
|
||||
// &&
|
||||
return Create<LexTokenImpl<LexTokenKind::AmpersandAmpersandSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -199,20 +199,19 @@ namespace MalachScript::Parser {
|
|||
// &
|
||||
return Create<LexTokenImpl<LexTokenKind::AmpersandSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8',': return Create<LexTokenImpl<LexTokenKind::CommaSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'{':
|
||||
return Create<LexTokenImpl<LexTokenKind::OpenCurlyParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'}':
|
||||
case ',': return Create<LexTokenImpl<LexTokenKind::CommaSymbol>>(TextSpan(start, start + 1));
|
||||
case '{': return Create<LexTokenImpl<LexTokenKind::OpenCurlyParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case '}':
|
||||
return Create<LexTokenImpl<LexTokenKind::CloseCurlyParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case u8';': return Create<LexTokenImpl<LexTokenKind::SemicolonSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'|': {
|
||||
case ';': return Create<LexTokenImpl<LexTokenKind::SemicolonSymbol>>(TextSpan(start, start + 1));
|
||||
case '|': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// |=
|
||||
return Create<LexTokenImpl<LexTokenKind::VerticalLineEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'|') {
|
||||
if (n == '|') {
|
||||
Progress();
|
||||
// ||
|
||||
return Create<LexTokenImpl<LexTokenKind::VerticalLineVerticalLineSymbol>>(
|
||||
|
@ -221,14 +220,14 @@ namespace MalachScript::Parser {
|
|||
// |
|
||||
return Create<LexTokenImpl<LexTokenKind::VerticalLineSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'^': {
|
||||
case '^': {
|
||||
auto n = Peek();
|
||||
if (n == u8'=') {
|
||||
if (n == '=') {
|
||||
Progress();
|
||||
// ^=
|
||||
return Create<LexTokenImpl<LexTokenKind::CaretEqualsSymbol>>(TextSpan(start, start + 2));
|
||||
}
|
||||
if (n == u8'^') {
|
||||
if (n == '^') {
|
||||
Progress();
|
||||
// ^^
|
||||
return Create<LexTokenImpl<LexTokenKind::CaretCaretSymbol>>(TextSpan(start, start + 2));
|
||||
|
@ -236,21 +235,20 @@ namespace MalachScript::Parser {
|
|||
// ^
|
||||
return Create<LexTokenImpl<LexTokenKind::CaretSymbol>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'~': return Create<LexTokenImpl<LexTokenKind::TildeSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'.': return Create<LexTokenImpl<LexTokenKind::DotSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'[':
|
||||
return Create<LexTokenImpl<LexTokenKind::OpenBlockParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case u8']':
|
||||
case '~': return Create<LexTokenImpl<LexTokenKind::TildeSymbol>>(TextSpan(start, start + 1));
|
||||
case '.': return Create<LexTokenImpl<LexTokenKind::DotSymbol>>(TextSpan(start, start + 1));
|
||||
case '[': return Create<LexTokenImpl<LexTokenKind::OpenBlockParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case ']':
|
||||
return Create<LexTokenImpl<LexTokenKind::CloseBlockParenthesisSymbol>>(TextSpan(start, start + 1));
|
||||
case u8'@': return Create<LexTokenImpl<LexTokenKind::AtSymbol>>(TextSpan(start, start + 1));
|
||||
case '@': return Create<LexTokenImpl<LexTokenKind::AtSymbol>>(TextSpan(start, start + 1));
|
||||
|
||||
case u8' ':
|
||||
case u8'\r':
|
||||
case u8'\n':
|
||||
case u8'\t': return Create<LexTokenImpl<LexTokenKind::Whitespace>>(TextSpan(start, start + 1));
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t': return Create<LexTokenImpl<LexTokenKind::Whitespace>>(TextSpan(start, start + 1));
|
||||
// Byte order mark
|
||||
case u8'\xEF': {
|
||||
if (Peek() == u8'\xBB' && Peek(2) == u8'\xBF') {
|
||||
case '\xEF': {
|
||||
if (Peek() == '\xBB' && Peek(2) == '\xBF') {
|
||||
Progress(2);
|
||||
return Create<LexTokenImpl<LexTokenKind::Whitespace>>(TextSpan(start, start + 3));
|
||||
}
|
||||
|
@ -258,22 +256,22 @@ namespace MalachScript::Parser {
|
|||
{std::string(1, c)});
|
||||
return Create<LexTokenImpl<LexTokenKind::Unknown>>(TextSpan(start, start + 1));
|
||||
}
|
||||
case u8'0':
|
||||
case u8'1':
|
||||
case u8'2':
|
||||
case u8'3':
|
||||
case u8'4':
|
||||
case u8'5':
|
||||
case u8'6':
|
||||
case u8'7':
|
||||
case u8'8':
|
||||
case u8'9': return LexNumerical(c);
|
||||
case u8'\'': return LexString(u8'\'', false);
|
||||
case u8'"': {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': return LexNumerical(c);
|
||||
case '\'': return LexString('\'', false);
|
||||
case '"': {
|
||||
if (Peek() == '"' && Peek(2) == '\"') {
|
||||
return LexString(u8'"', true);
|
||||
return LexString('"', true);
|
||||
}
|
||||
return LexString(u8'"', false);
|
||||
return LexString('"', false);
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -285,7 +283,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
}
|
||||
|
||||
LexToken* Lexer::LexNumerical(char8_t c) {
|
||||
LexToken* Lexer::LexNumerical(char c) {
|
||||
auto initialValue = LexDecimalValue(c);
|
||||
auto numericalSystem = 10; // Default to decimal system.
|
||||
if (initialValue == 0) {
|
||||
|
@ -361,12 +359,12 @@ namespace MalachScript::Parser {
|
|||
while (true) {
|
||||
auto v = (ParseInt)LexDecimalValue(Peek());
|
||||
if (v == 255) {
|
||||
if (!isDecimal && Peek() == u8'.') {
|
||||
if (!isDecimal && Peek() == '.') {
|
||||
isDecimal = true;
|
||||
Progress();
|
||||
continue;
|
||||
}
|
||||
if (isDecimal && (Peek() == u8'e' || Peek() == u8'E')) {
|
||||
if (isDecimal && (Peek() == 'e' || Peek() == 'E')) {
|
||||
isDecimal = false;
|
||||
isExponent = true;
|
||||
Progress();
|
||||
|
@ -439,7 +437,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
return Create<IntegerLiteral>(TextSpan(start - 1, _position), value);
|
||||
}
|
||||
StringLiteral* Lexer::LexString(char8_t opening, bool heredoc) {
|
||||
StringLiteral* Lexer::LexString(char opening, bool heredoc) {
|
||||
auto openingPos = _position;
|
||||
Progress();
|
||||
if (heredoc) {
|
||||
|
@ -456,12 +454,12 @@ namespace MalachScript::Parser {
|
|||
} else if (current == opening) {
|
||||
break;
|
||||
}
|
||||
if (current == u8'\0') {
|
||||
if (current == '\0') {
|
||||
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString, TextSpan(start, start + offset),
|
||||
{"EndOfFile"});
|
||||
break;
|
||||
}
|
||||
if (!heredoc && (current == u8'\n' || current == u8'\r')) {
|
||||
if (!heredoc && (current == '\n' || current == '\r')) {
|
||||
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString, TextSpan(start, start + offset),
|
||||
{"Newline"});
|
||||
break;
|
||||
|
@ -486,139 +484,139 @@ namespace MalachScript::Parser {
|
|||
Progress(offset - 1);
|
||||
auto hash = Identifier::Hash(str);
|
||||
switch (hash) {
|
||||
case Identifier::Hash(u8"and"):
|
||||
case Identifier::Hash("and"):
|
||||
return Create<LexTokenImpl<LexTokenKind::AndKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"abstract"):
|
||||
case Identifier::Hash("abstract"):
|
||||
return Create<LexTokenImpl<LexTokenKind::AbstractKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"auto"):
|
||||
case Identifier::Hash("auto"):
|
||||
return Create<LexTokenImpl<LexTokenKind::AutoKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"bool"):
|
||||
case Identifier::Hash("bool"):
|
||||
return Create<LexTokenImpl<LexTokenKind::BoolKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"break"):
|
||||
case Identifier::Hash("break"):
|
||||
return Create<LexTokenImpl<LexTokenKind::BreakKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"case"):
|
||||
case Identifier::Hash("case"):
|
||||
return Create<LexTokenImpl<LexTokenKind::CaseKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"cast"):
|
||||
case Identifier::Hash("cast"):
|
||||
return Create<LexTokenImpl<LexTokenKind::CastKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"catch"):
|
||||
case Identifier::Hash("catch"):
|
||||
return Create<LexTokenImpl<LexTokenKind::CatchKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"class"):
|
||||
case Identifier::Hash("class"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ClassKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"const"):
|
||||
case Identifier::Hash("const"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ConstKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"continue"):
|
||||
case Identifier::Hash("continue"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ContinueKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"default"):
|
||||
case Identifier::Hash("default"):
|
||||
return Create<LexTokenImpl<LexTokenKind::DefaultKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"do"):
|
||||
case Identifier::Hash("do"):
|
||||
return Create<LexTokenImpl<LexTokenKind::DoKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"double"):
|
||||
case Identifier::Hash("double"):
|
||||
return Create<LexTokenImpl<LexTokenKind::DoubleKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"else"):
|
||||
case Identifier::Hash("else"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ElseKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"enum"):
|
||||
case Identifier::Hash("enum"):
|
||||
return Create<LexTokenImpl<LexTokenKind::EnumKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"explicit"):
|
||||
case Identifier::Hash("explicit"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ExplicitKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"external"):
|
||||
case Identifier::Hash("external"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ExternalKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"false"):
|
||||
case Identifier::Hash("false"):
|
||||
return Create<LexTokenImpl<LexTokenKind::FalseKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"final"):
|
||||
case Identifier::Hash("final"):
|
||||
return Create<LexTokenImpl<LexTokenKind::FinalKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"float"):
|
||||
case Identifier::Hash("float"):
|
||||
return Create<LexTokenImpl<LexTokenKind::FloatKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"for"):
|
||||
case Identifier::Hash("for"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ForKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"from"):
|
||||
case Identifier::Hash("from"):
|
||||
return Create<LexTokenImpl<LexTokenKind::FromKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"funcdef"):
|
||||
case Identifier::Hash("funcdef"):
|
||||
return Create<LexTokenImpl<LexTokenKind::FuncdefKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"function"):
|
||||
case Identifier::Hash("function"):
|
||||
return Create<LexTokenImpl<LexTokenKind::FunctionKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"get"):
|
||||
case Identifier::Hash("get"):
|
||||
return Create<LexTokenImpl<LexTokenKind::GetKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"if"):
|
||||
case Identifier::Hash("if"):
|
||||
return Create<LexTokenImpl<LexTokenKind::IfKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"import"):
|
||||
case Identifier::Hash("import"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ImportKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"in"):
|
||||
case Identifier::Hash("in"):
|
||||
return Create<LexTokenImpl<LexTokenKind::InKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"inout"):
|
||||
case Identifier::Hash("inout"):
|
||||
return Create<LexTokenImpl<LexTokenKind::InoutKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"int"):
|
||||
case Identifier::Hash("int"):
|
||||
return Create<LexTokenImpl<LexTokenKind::IntKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"interface"):
|
||||
case Identifier::Hash("interface"):
|
||||
return Create<LexTokenImpl<LexTokenKind::InterfaceKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"int8"):
|
||||
case Identifier::Hash("int8"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Int8Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"int16"):
|
||||
case Identifier::Hash("int16"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Int16Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"int32"):
|
||||
case Identifier::Hash("int32"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Int32Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"int64"):
|
||||
case Identifier::Hash("int64"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Int64Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"is"):
|
||||
case Identifier::Hash("is"):
|
||||
return Create<LexTokenImpl<LexTokenKind::IsKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"mixin"):
|
||||
case Identifier::Hash("mixin"):
|
||||
return Create<LexTokenImpl<LexTokenKind::MixinKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"namespace"):
|
||||
case Identifier::Hash("namespace"):
|
||||
return Create<LexTokenImpl<LexTokenKind::NamespaceKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"not"):
|
||||
case Identifier::Hash("not"):
|
||||
return Create<LexTokenImpl<LexTokenKind::NotKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"null"):
|
||||
case Identifier::Hash("null"):
|
||||
return Create<LexTokenImpl<LexTokenKind::NullKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"or"):
|
||||
case Identifier::Hash("or"):
|
||||
return Create<LexTokenImpl<LexTokenKind::OrKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"out"):
|
||||
case Identifier::Hash("out"):
|
||||
return Create<LexTokenImpl<LexTokenKind::OutKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"override"):
|
||||
case Identifier::Hash("override"):
|
||||
return Create<LexTokenImpl<LexTokenKind::OverrideKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"private"):
|
||||
case Identifier::Hash("private"):
|
||||
return Create<LexTokenImpl<LexTokenKind::PrivateKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"property"):
|
||||
case Identifier::Hash("property"):
|
||||
return Create<LexTokenImpl<LexTokenKind::PropertyKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"protected"):
|
||||
case Identifier::Hash("protected"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ProtectedKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"return"):
|
||||
case Identifier::Hash("return"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ReturnKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"set"):
|
||||
case Identifier::Hash("set"):
|
||||
return Create<LexTokenImpl<LexTokenKind::SetKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"shared"):
|
||||
case Identifier::Hash("shared"):
|
||||
return Create<LexTokenImpl<LexTokenKind::SharedKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"super"):
|
||||
case Identifier::Hash("super"):
|
||||
return Create<LexTokenImpl<LexTokenKind::SuperKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"switch"):
|
||||
case Identifier::Hash("switch"):
|
||||
return Create<LexTokenImpl<LexTokenKind::SwitchKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"this"):
|
||||
case Identifier::Hash("this"):
|
||||
return Create<LexTokenImpl<LexTokenKind::ThisKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"true"):
|
||||
case Identifier::Hash("true"):
|
||||
return Create<LexTokenImpl<LexTokenKind::TrueKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"try"):
|
||||
case Identifier::Hash("try"):
|
||||
return Create<LexTokenImpl<LexTokenKind::TryKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"typedef"):
|
||||
case Identifier::Hash("typedef"):
|
||||
return Create<LexTokenImpl<LexTokenKind::TypedefKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"uint"):
|
||||
case Identifier::Hash("uint"):
|
||||
return Create<LexTokenImpl<LexTokenKind::UintKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"uint8"):
|
||||
case Identifier::Hash("uint8"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Uint8Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"uint16"):
|
||||
case Identifier::Hash("uint16"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Uint16Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"uint32"):
|
||||
case Identifier::Hash("uint32"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Uint32Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"uint64"):
|
||||
case Identifier::Hash("uint64"):
|
||||
return Create<LexTokenImpl<LexTokenKind::Uint64Keyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"void"):
|
||||
case Identifier::Hash("void"):
|
||||
return Create<LexTokenImpl<LexTokenKind::VoidKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"while"):
|
||||
case Identifier::Hash("while"):
|
||||
return Create<LexTokenImpl<LexTokenKind::WhileKeyword>>(TextSpan(start, _position));
|
||||
case Identifier::Hash(u8"xor"):
|
||||
case Identifier::Hash("xor"):
|
||||
return Create<LexTokenImpl<LexTokenKind::XorKeyword>>(TextSpan(start, _position));
|
||||
|
||||
default: return Create<IdentifierToken>(TextSpan(start, _position), Identifier(str.data(), offset, hash));
|
||||
}
|
||||
}
|
||||
bool Lexer::IsAlphaNumericalOrUnderscore(char8_t c) {
|
||||
bool Lexer::IsAlphaNumericalOrUnderscore(char c) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -9,22 +9,22 @@
|
|||
namespace MalachScript::Parser {
|
||||
class Lexer {
|
||||
public:
|
||||
Lexer(const char8_t* scriptName, const char8_t* script, Diagnostics::Logger* diag)
|
||||
: Lexer(std::u8string_view(scriptName), std::u8string_view(script), diag) {}
|
||||
Lexer(std::u8string_view scriptName, std::u8string_view script, Diagnostics::Logger* diag)
|
||||
Lexer(const char* scriptName, const char* script, Diagnostics::Logger* diag)
|
||||
: Lexer(std::string_view(scriptName), std::string_view(script), diag) {}
|
||||
Lexer(std::string_view scriptName, std::string_view script, Diagnostics::Logger* diag)
|
||||
: _scriptName(scriptName), _script(script), _scriptLength(script.size()), _diagnostics(diag) {}
|
||||
const LexToken* Lex();
|
||||
|
||||
private:
|
||||
std::u8string_view _scriptName;
|
||||
std::u8string_view _script;
|
||||
std::string_view _scriptName;
|
||||
std::string_view _script;
|
||||
size_t _position = -1;
|
||||
size_t _scriptLength;
|
||||
Diagnostics::Logger* _diagnostics;
|
||||
|
||||
Utils::MemoryPool<4096> _allocator;
|
||||
|
||||
inline char8_t Consume() {
|
||||
inline char Consume() {
|
||||
if (++_position >= _scriptLength) {
|
||||
return '\0';
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace MalachScript::Parser {
|
|||
|
||||
inline void Progress(size_t steps = 1) { _position += steps; }
|
||||
|
||||
inline char8_t Peek(size_t offset = 1) {
|
||||
inline char Peek(size_t offset = 1) {
|
||||
auto pos = _position + offset;
|
||||
if (pos >= _scriptLength) {
|
||||
return '\0';
|
||||
|
@ -42,16 +42,16 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
|
||||
LexToken* LexNext();
|
||||
LexToken* LexNumerical(char8_t);
|
||||
LexToken* LexNumerical(char);
|
||||
LexToken* LexDecimal(uint64_t initial);
|
||||
IntegerLiteral* LexHexadecimal();
|
||||
IntegerLiteral* LexOctal();
|
||||
IntegerLiteral* LexBinary();
|
||||
|
||||
StringLiteral* LexString(char8_t opening, bool heredoc);
|
||||
StringLiteral* LexString(char opening, bool heredoc);
|
||||
LexToken* LexKeywordOrIdentifier();
|
||||
|
||||
static bool IsAlphaNumericalOrUnderscore(char8_t c);
|
||||
static bool IsAlphaNumericalOrUnderscore(char c);
|
||||
|
||||
template <class T, class... parameters> inline T* Create(parameters... args) {
|
||||
return _allocator.Create<T>(args...);
|
||||
|
|
|
@ -1,66 +1,66 @@
|
|||
#include "NumericalLexers.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
uint8_t LexDecimalValue(char8_t c) {
|
||||
uint8_t LexDecimalValue(char c) {
|
||||
switch (c) {
|
||||
case u8'0': return 0;
|
||||
case u8'1': return 1;
|
||||
case u8'2': return 2;
|
||||
case u8'3': return 3;
|
||||
case u8'4': return 4;
|
||||
case u8'5': return 5;
|
||||
case u8'6': return 6;
|
||||
case u8'7': return 7;
|
||||
case u8'8': return 8;
|
||||
case u8'9': return 9;
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
default: return 255;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t LexHexadecimalValue(char8_t c) {
|
||||
uint8_t LexHexadecimalValue(char c) {
|
||||
switch (c) {
|
||||
case u8'0': return 0;
|
||||
case u8'1': return 1;
|
||||
case u8'2': return 2;
|
||||
case u8'3': return 3;
|
||||
case u8'4': return 4;
|
||||
case u8'5': return 5;
|
||||
case u8'6': return 6;
|
||||
case u8'7': return 7;
|
||||
case u8'8': return 8;
|
||||
case u8'9': return 9;
|
||||
case u8'a':
|
||||
case u8'A': return 10;
|
||||
case u8'b':
|
||||
case u8'B': return 11;
|
||||
case u8'c':
|
||||
case u8'C': return 12;
|
||||
case u8'd':
|
||||
case u8'D': return 13;
|
||||
case u8'e':
|
||||
case u8'E': return 14;
|
||||
case u8'f':
|
||||
case u8'F': return 15;
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
case 'a':
|
||||
case 'A': return 10;
|
||||
case 'b':
|
||||
case 'B': return 11;
|
||||
case 'c':
|
||||
case 'C': return 12;
|
||||
case 'd':
|
||||
case 'D': return 13;
|
||||
case 'e':
|
||||
case 'E': return 14;
|
||||
case 'f':
|
||||
case 'F': return 15;
|
||||
default: return 255;
|
||||
}
|
||||
}
|
||||
uint8_t LexOctalValue(char8_t c) {
|
||||
uint8_t LexOctalValue(char c) {
|
||||
switch (c) {
|
||||
case u8'0': return 0;
|
||||
case u8'1': return 1;
|
||||
case u8'2': return 2;
|
||||
case u8'3': return 3;
|
||||
case u8'4': return 4;
|
||||
case u8'5': return 5;
|
||||
case u8'6': return 6;
|
||||
case u8'7': return 7;
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
default: return 255;
|
||||
}
|
||||
}
|
||||
uint8_t LexBinaryValue(char8_t c) {
|
||||
uint8_t LexBinaryValue(char c) {
|
||||
switch (c) {
|
||||
case u8'0': return 0;
|
||||
case u8'1': return 1;
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
default: return 255;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
uint8_t LexDecimalValue(char8_t c);
|
||||
uint8_t LexHexadecimalValue(char8_t c);
|
||||
uint8_t LexOctalValue(char8_t c);
|
||||
uint8_t LexBinaryValue(char8_t c);
|
||||
uint8_t LexDecimalValue(char c);
|
||||
uint8_t LexHexadecimalValue(char c);
|
||||
uint8_t LexOctalValue(char c);
|
||||
uint8_t LexBinaryValue(char c);
|
||||
|
||||
#endif // MALACHSCRIPT_NUMERICALLEXERS_HPP
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
namespace MalachScript::Parser {
|
||||
using namespace Diagnostics;
|
||||
|
||||
const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
||||
const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, std::string_view scriptName,
|
||||
Logger* diagnostics) {
|
||||
const log_func& log = [diagnostics, scriptName](DiagnosticLevel level, DiagnosticType type,
|
||||
const TextSpan& span, const std::vector<std::string>& formats) {
|
||||
|
@ -252,7 +252,7 @@ namespace MalachScript::Parser {
|
|||
accessModifier = AccessModifier::Protected;
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||
ScopedPtr<const ParsedTypeStatement> typeStatement = nullptr;
|
||||
bool returnsReference = false;
|
||||
if (current->GetKind() == LexTokenKind::TildeSymbol) {
|
||||
// TODO: Handle destructor
|
||||
|
@ -295,7 +295,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func& log) {
|
||||
bool Parser::ParseType(ScopedPtr<const ParsedTypeStatement>& out, const LexToken*& currentToken,
|
||||
const log_func& log) {
|
||||
const auto* current = currentToken;
|
||||
auto start = current->GetSpan().GetStart();
|
||||
bool isConst = false;
|
||||
|
@ -420,7 +421,7 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
while (true) {
|
||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||
ScopedPtr<const ParsedTypeStatement> typeStatement = nullptr;
|
||||
TypeMod typeMod = TypeMod::None;
|
||||
Identifier identifier;
|
||||
const ParsedStatement* defaultExpression = nullptr;
|
||||
|
@ -480,7 +481,7 @@ namespace MalachScript::Parser {
|
|||
access = AccessModifier::Protected;
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||
ScopedPtr<const ParsedTypeStatement> typeStatement = nullptr;
|
||||
if (!ParseType(typeStatement, current, log)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -623,7 +624,7 @@ namespace MalachScript::Parser {
|
|||
access = AccessModifier::Protected;
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||
ScopedPtr<const ParsedTypeStatement> typeStatement = nullptr;
|
||||
if (!ParseType(typeStatement, current, log)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace MalachScript::Parser {
|
||||
class Parser {
|
||||
public:
|
||||
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
||||
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::string_view scriptName,
|
||||
Diagnostics::Logger* diagnostics);
|
||||
|
||||
private:
|
||||
|
@ -110,7 +110,8 @@ namespace MalachScript::Parser {
|
|||
static bool ParsePrimType(Identifier& out, const LexToken*& currentToken, const log_func&);
|
||||
static bool ParseDataType(Identifier& out, const LexToken*& currentToken, const log_func&);
|
||||
static bool ParseScope(std::vector<Identifier>& out, const LexToken*& currentToken, const log_func&);
|
||||
static bool ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||
static bool ParseType(ScopedPtr<const ParsedTypeStatement>& out, const LexToken*& currentToken,
|
||||
const log_func&);
|
||||
static bool ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||
// InitList
|
||||
inline static bool ParsePreOp(PreOperator& op, const LexToken*& token, const log_func&) {
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
|
||||
using ParseInt = uintmax_t;
|
||||
using ParseFloat = long double;
|
||||
using ParseString = std::u8string;
|
||||
using ParseString = std::string;
|
||||
|
||||
#endif // MALACHSCRIPT_PARSERDEFINES_HPP
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
||||
#define MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
|
@ -8,6 +9,7 @@
|
|||
#include "../../CoreData/AccessModifier.hpp"
|
||||
#include "../../CoreData/ClassAttr.hpp"
|
||||
#include "../../CoreData/FuncAttr.hpp"
|
||||
#include "../../CoreData/Identifier.hpp"
|
||||
#include "../../CoreData/TypeMod.hpp"
|
||||
#include "../../TextSpan.hpp"
|
||||
#include "ParsedStatementKind.hpp"
|
||||
|
@ -46,11 +48,12 @@ namespace MalachScript::Parser {
|
|||
class ParsedClassStatement : public ParsedStatementImpl<ParsedStatementKind::Class> {
|
||||
public:
|
||||
ParsedClassStatement(TextSpan span, ClassAttr classAttr, Identifier identifier,
|
||||
std::vector<Identifier> inherits, const std::vector<const ParsedStatement*>& body)
|
||||
const std::vector<Identifier>& inherits, const std::vector<const ParsedStatement*>& body)
|
||||
: ParsedStatementImpl<ParsedStatementKind::Class>(span), _classAttr(classAttr), _identifier(identifier),
|
||||
_inherits(inherits), _body(body.size()) {
|
||||
for (size_t i = 0; i < body.size(); i++)
|
||||
for (size_t i = 0; i < body.size(); i++) {
|
||||
_body[i] = std::unique_ptr<const ParsedStatement>(body[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] ClassAttr GetClassAttr() const noexcept { return _classAttr; }
|
||||
|
@ -269,21 +272,21 @@ namespace MalachScript::Parser {
|
|||
std::vector<std::unique_ptr<const ParsedStatement>> _statements;
|
||||
};
|
||||
|
||||
class ParsedVarStatement : public ParsedStatementImpl<ParsedStatementKind::StatBlock> {
|
||||
class ParsedVarStatement : public ParsedStatementImpl<ParsedStatementKind::Var> {
|
||||
public:
|
||||
ParsedVarStatement(const TextSpan& span, AccessModifier access, const ParsedStatement* typeStatement,
|
||||
ParsedVarStatement(const TextSpan& span, AccessModifier access, const ParsedTypeStatement* typeStatement,
|
||||
Identifier identifier)
|
||||
: ParsedStatementImpl(span), _access(access), _typeStatement(typeStatement), _identifier(identifier) {}
|
||||
|
||||
[[nodiscard]] AccessModifier GetAccess() const noexcept { return _access; }
|
||||
[[nodiscard]] const std::unique_ptr<const ParsedStatement>& GetTypeStatement() const noexcept {
|
||||
[[nodiscard]] const std::unique_ptr<const ParsedTypeStatement>& GetTypeStatement() const noexcept {
|
||||
return _typeStatement;
|
||||
}
|
||||
[[nodiscard]] const Identifier& GetIdentifier() const noexcept { return _identifier; }
|
||||
|
||||
private:
|
||||
AccessModifier _access;
|
||||
std::unique_ptr<const ParsedStatement> _typeStatement;
|
||||
std::unique_ptr<const ParsedTypeStatement> _typeStatement;
|
||||
Identifier _identifier;
|
||||
};
|
||||
|
||||
|
@ -468,7 +471,6 @@ namespace MalachScript::Parser {
|
|||
std::unique_ptr<const ParsedStatement> _expression;
|
||||
std::vector<std::unique_ptr<const ParsedStatement>> _statements;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace MalachScript::Parser {
|
|||
Func,
|
||||
VirtProp,
|
||||
StatBlock,
|
||||
Var,
|
||||
If,
|
||||
Assign,
|
||||
BinaryExpression,
|
||||
|
@ -46,6 +47,7 @@ namespace MalachScript::Parser {
|
|||
case ParsedStatementKind::Func: return "Func";
|
||||
case ParsedStatementKind::VirtProp: return "VirtProp";
|
||||
case ParsedStatementKind::StatBlock: return "StatBlock";
|
||||
case ParsedStatementKind::Var: return "Var";
|
||||
case ParsedStatementKind::If: return "If";
|
||||
case ParsedStatementKind::Assign: return "Assign";
|
||||
case ParsedStatementKind::BinaryExpression: return "BinaryExpression";
|
||||
|
|
|
@ -193,6 +193,7 @@ namespace MalachScript::Parser {
|
|||
case ParsedStatementKind::Try: break;
|
||||
case ParsedStatementKind::Switch: break;
|
||||
case ParsedStatementKind::Case: break;
|
||||
case ParsedStatementKind::Var: break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "ScriptEngine.hpp"
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef MALACHSCRIPT_SCRIPTENGINE_HPP
|
||||
#define MALACHSCRIPT_SCRIPTENGINE_HPP
|
||||
|
||||
namespace MalachScript {
|
||||
class ScriptEngine {
|
||||
public:
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_SCRIPTENGINE_HPP
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef MALACHSCRIPT_TREEPRINTER_HPP
|
||||
#define MALACHSCRIPT_TREEPRINTER_HPP
|
||||
#include <sstream>
|
||||
|
||||
class MalachScript::Utils {
|
||||
class TreePrinter {
|
||||
public:
|
||||
private:
|
||||
std::stringstream _stream;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // MALACHSCRIPT_TREEPRINTER_HPP
|
|
@ -6,7 +6,7 @@ using namespace MalachScript::Parser;
|
|||
#define KEYWORD_TEST(script, symbol) \
|
||||
TEST_CASE("Lex " script) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||
auto lexer = Lexer(script, script, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
CHECK(token->GetKind() == LexTokenKind::symbol); \
|
||||
|
@ -79,10 +79,8 @@ KEYWORD_TEST("while", WhileKeyword);
|
|||
KEYWORD_TEST("xor", XorKeyword);
|
||||
|
||||
namespace doctest {
|
||||
template <> struct StringMaker<std::u8string> {
|
||||
static String convert(const std::u8string& value) {
|
||||
return String(reinterpret_cast<const char*>(value.data()));
|
||||
}
|
||||
template <> struct StringMaker<std::string> {
|
||||
static String convert(const std::string& value) { return String(reinterpret_cast<const char*>(value.data())); }
|
||||
};
|
||||
template <> struct StringMaker<LexTokenKind> {
|
||||
static String convert(LexTokenKind value) { return String(std::to_string((uint32_t)value).c_str()); }
|
||||
|
@ -93,12 +91,12 @@ namespace doctest {
|
|||
#define IDENTIFIER_TEST(identifier) \
|
||||
TEST_CASE("Lex identifier " identifier) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##identifier, u8##identifier, &diag); \
|
||||
auto lexer = Lexer(identifier, identifier, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
REQUIRE(token->GetKind() == LexTokenKind::Identifier); \
|
||||
auto value = ((IdentifierToken*)token)->GetValue().GetString(); \
|
||||
CHECK(value == std::u8string(reinterpret_cast<const char8_t*>(identifier))); \
|
||||
CHECK(value == std::string(reinterpret_cast<const char*>(identifier))); \
|
||||
CHECK(token->GetNext()->GetKind() == LexTokenKind::EndOfFile); \
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ using namespace MalachScript::Parser;
|
|||
#define LEX_TEST(script, ...) \
|
||||
TEST_CASE("Lex: " script) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||
auto lexer = Lexer(script, script, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
std::vector<LexTokenKind> vec = {__VA_ARGS__, LexTokenKind::EndOfFile}; \
|
||||
|
|
|
@ -6,7 +6,7 @@ using namespace MalachScript::Parser;
|
|||
#define INTEGER_TEST(script, expected) \
|
||||
TEST_CASE("Lex " script) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||
auto lexer = Lexer(script, script, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
REQUIRE(token->GetKind() == LexTokenKind::IntegerLiteral); \
|
||||
|
@ -18,7 +18,7 @@ using namespace MalachScript::Parser;
|
|||
#define FLOAT_TEST(script, expected) \
|
||||
TEST_CASE("Lex " script) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||
auto lexer = Lexer(script, script, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
REQUIRE(token->GetKind() == LexTokenKind::FloatLiteral); \
|
||||
|
|
|
@ -6,12 +6,12 @@ using namespace MalachScript::Parser;
|
|||
#define STRING_TEST(str, constraint) \
|
||||
TEST_CASE("Lex string " constraint str constraint) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##str, u8##constraint str constraint, &diag); \
|
||||
auto lexer = Lexer(str, constraint str constraint, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
REQUIRE(token->GetKind() == LexTokenKind::StringLiteral); \
|
||||
auto value = ((const StringLiteral*)token)->GetValue(); \
|
||||
CHECK(value == std::u8string(reinterpret_cast<const char8_t*>(str))); \
|
||||
CHECK(value == std::string(reinterpret_cast<const char*>(str))); \
|
||||
CHECK(token->GetNext()->GetKind() == LexTokenKind::EndOfFile); \
|
||||
}
|
||||
|
||||
|
@ -23,14 +23,14 @@ STRING_TEST("\"\"foo bar\"\"", "\"\"\"");
|
|||
|
||||
TEST_CASE("Lex multiline string") {
|
||||
MalachScript::Diagnostics::Logger diag;
|
||||
auto lexer = Lexer(u8"multiline", u8R"("""foo
|
||||
auto lexer = Lexer("multiline", R"("""foo
|
||||
bar""")",
|
||||
&diag);
|
||||
const auto* token = lexer.Lex();
|
||||
CHECK(diag.GetMessages().empty());
|
||||
REQUIRE(token->GetKind() == LexTokenKind::StringLiteral);
|
||||
auto value = (dynamic_cast<const StringLiteral*>(token))->GetValue();
|
||||
CHECK(value == std::u8string(reinterpret_cast<const char8_t*>(R"(foo
|
||||
CHECK(value == std::string(reinterpret_cast<const char*>(R"(foo
|
||||
bar)")));
|
||||
CHECK(token->GetNext()->GetKind() == LexTokenKind::EndOfFile);
|
||||
}
|
|
@ -7,7 +7,7 @@ using namespace MalachScript::Parser;
|
|||
#define SYMBOL_TEST(script, symbol) \
|
||||
TEST_CASE("Lex " script) { \
|
||||
MalachScript::Diagnostics::Logger diag; \
|
||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||
auto lexer = Lexer(script, script, &diag); \
|
||||
const auto* token = lexer.Lex(); \
|
||||
CHECK(diag.GetMessages().empty()); \
|
||||
CHECK(token->GetKind() == LexTokenKind::symbol); \
|
||||
|
@ -71,10 +71,10 @@ SYMBOL_TEST(" ", Whitespace)
|
|||
#undef SYMBOL_TEST
|
||||
|
||||
TEST_CASE("Lex whitespace") {
|
||||
auto whitespace = {u8" ", u8"\t", u8"\n", u8"\r", u8"\xef\xbb\xbf"};
|
||||
auto whitespace = {" ", "\t", "\n", "\r", "\xef\xbb\xbf"};
|
||||
for (const auto* v : whitespace) {
|
||||
MalachScript::Diagnostics::Logger diag;
|
||||
auto lexer = Lexer(u8"whitespace", v, &diag);
|
||||
auto lexer = Lexer("whitespace", v, &diag);
|
||||
const auto* token = lexer.Lex();
|
||||
CHECK(diag.GetMessages().empty());
|
||||
CHECK(token->GetKind() == LexTokenKind::Whitespace);
|
||||
|
|
|
@ -13,7 +13,7 @@ using namespace MalachScript;
|
|||
vec[i]->SetNext(vec[i + 1]); \
|
||||
} \
|
||||
Diagnostics::Logger diags; \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), "scriptname", &diags); \
|
||||
REQUIRE(diags.GetMessages().empty()); \
|
||||
asserts; \
|
||||
delete vec[0]; \
|
||||
|
@ -24,7 +24,7 @@ using namespace MalachScript;
|
|||
|
||||
PARSER_TEST("Parse basic class without body",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0))),
|
||||
{
|
||||
REQUIRE(script->GetStatements().size() == 1);
|
||||
|
@ -34,7 +34,7 @@ PARSER_TEST("Parse basic class without body",
|
|||
PARSER_TEST("Parse basic class without body with whitespaces",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0))),
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ PARSER_TEST("Parse basic class without body with whitespaces",
|
|||
PARSER_TEST(
|
||||
"Parse basic class with empty body",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ using namespace MalachScript;
|
|||
vec[i]->SetNext(vec[i + 1]); \
|
||||
} \
|
||||
Diagnostics::Logger diags; \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), "scriptname", &diags); \
|
||||
REQUIRE(diags.GetMessages().empty()); \
|
||||
asserts; \
|
||||
delete vec[0]; \
|
||||
|
@ -25,7 +25,7 @@ using namespace MalachScript;
|
|||
PARSER_TEST("Parse ``void foobar();``",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::VoidKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0))),
|
||||
|
@ -41,9 +41,9 @@ PARSER_TEST("Parse ``void foobar();``",
|
|||
CHECK_FALSE(type->IsArray());
|
||||
CHECK_FALSE(type->IsHandle());
|
||||
auto& id = type->GetScopedIdentifier();
|
||||
CHECK(id.GetIdentifier().GetString() == u8"void");
|
||||
CHECK(id.GetIdentifier().GetString() == "void");
|
||||
CHECK_FALSE(funcStat->ReturnsReference());
|
||||
CHECK(funcStat->GetIdentifier().GetString() == u8"foobar");
|
||||
CHECK(funcStat->GetIdentifier().GetString() == "foobar");
|
||||
auto paramList = (const MalachScript::Parser::ParsedParamListStatement*)funcStat->GetParamList().get();
|
||||
CHECK(paramList->GetParameters().empty());
|
||||
CHECK_FALSE(funcStat->IsConst());
|
||||
|
@ -52,13 +52,13 @@ PARSER_TEST("Parse ``void foobar();``",
|
|||
})
|
||||
|
||||
PARSER_TEST("Parse scoped function without body.",
|
||||
PARSER_TEST_TOKENS(new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
PARSER_TEST_TOKENS(new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ColonColonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ColonColonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"baz"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "baz"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0))),
|
||||
|
@ -74,11 +74,11 @@ PARSER_TEST("Parse scoped function without body.",
|
|||
CHECK_FALSE(type->IsArray());
|
||||
CHECK_FALSE(type->IsHandle());
|
||||
auto& id = type->GetScopedIdentifier();
|
||||
CHECK(id.GetIdentifier().GetString() == u8"baz");
|
||||
CHECK(id.GetScope()[1].GetString() == u8"bar");
|
||||
CHECK(id.GetScope()[0].GetString() == u8"foo");
|
||||
CHECK(id.GetIdentifier().GetString() == "baz");
|
||||
CHECK(id.GetScope()[1].GetString() == "bar");
|
||||
CHECK(id.GetScope()[0].GetString() == "foo");
|
||||
CHECK_FALSE(funcStat->ReturnsReference());
|
||||
CHECK(funcStat->GetIdentifier().GetString() == u8"foobar");
|
||||
CHECK(funcStat->GetIdentifier().GetString() == "foobar");
|
||||
auto paramList = (const MalachScript::Parser::ParsedParamListStatement*)funcStat->GetParamList().get();
|
||||
CHECK(paramList->GetParameters().empty());
|
||||
CHECK_FALSE(funcStat->IsConst());
|
||||
|
@ -87,24 +87,24 @@ PARSER_TEST("Parse scoped function without body.",
|
|||
})
|
||||
|
||||
PARSER_TEST("Parse scoped function with parameters without body.",
|
||||
PARSER_TEST_TOKENS(new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
PARSER_TEST_TOKENS(new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ColonColonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ColonColonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"baz"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "baz"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IntKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"par1"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "par1"),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CommaSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::BoolKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"par2"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "par2"),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0))),
|
||||
|
@ -120,11 +120,11 @@ PARSER_TEST("Parse scoped function with parameters without body.",
|
|||
CHECK_FALSE(type->IsArray());
|
||||
CHECK_FALSE(type->IsHandle());
|
||||
auto& id = type->GetScopedIdentifier();
|
||||
CHECK(id.GetIdentifier().GetString() == u8"baz");
|
||||
CHECK(id.GetScope()[1].GetString() == u8"bar");
|
||||
CHECK(id.GetScope()[0].GetString() == u8"foo");
|
||||
CHECK(id.GetIdentifier().GetString() == "baz");
|
||||
CHECK(id.GetScope()[1].GetString() == "bar");
|
||||
CHECK(id.GetScope()[0].GetString() == "foo");
|
||||
CHECK_FALSE(funcStat->ReturnsReference());
|
||||
CHECK(funcStat->GetIdentifier().GetString() == u8"foobar");
|
||||
CHECK(funcStat->GetIdentifier().GetString() == "foobar");
|
||||
auto paramList = (const MalachScript::Parser::ParsedParamListStatement*)funcStat->GetParamList().get();
|
||||
CHECK(paramList->GetParameters().size() == 2);
|
||||
|
||||
|
@ -133,9 +133,9 @@ PARSER_TEST("Parse scoped function with parameters without body.",
|
|||
CHECK_FALSE(par1.GetTypeStatement()->IsArray());
|
||||
CHECK_FALSE(par1.GetTypeStatement()->IsHandle());
|
||||
auto& par1TypeId = par1.GetTypeStatement()->GetScopedIdentifier();
|
||||
CHECK(par1TypeId.GetIdentifier().GetString() == u8"int");
|
||||
CHECK(par1TypeId.GetIdentifier().GetString() == "int");
|
||||
CHECK(par1.GetTypeMod() == TypeMod::None);
|
||||
CHECK(par1.GetIdentifier().GetString() == u8"par1");
|
||||
CHECK(par1.GetIdentifier().GetString() == "par1");
|
||||
CHECK(par1.GetDefaultExpression() == nullptr);
|
||||
|
||||
auto& par2 = *paramList->GetParameters()[1];
|
||||
|
@ -143,9 +143,9 @@ PARSER_TEST("Parse scoped function with parameters without body.",
|
|||
CHECK_FALSE(par2.GetTypeStatement()->IsArray());
|
||||
CHECK_FALSE(par2.GetTypeStatement()->IsHandle());
|
||||
auto& par2TypeId = par2.GetTypeStatement()->GetScopedIdentifier();
|
||||
CHECK(par2TypeId.GetIdentifier().GetString() == u8"bool");
|
||||
CHECK(par2TypeId.GetIdentifier().GetString() == "bool");
|
||||
CHECK(par2.GetTypeMod() == TypeMod::None);
|
||||
CHECK(par2.GetIdentifier().GetString() == u8"par2");
|
||||
CHECK(par2.GetIdentifier().GetString() == "par2");
|
||||
CHECK(par2.GetDefaultExpression() == nullptr);
|
||||
|
||||
CHECK_FALSE(funcStat->IsConst());
|
||||
|
@ -154,20 +154,20 @@ PARSER_TEST("Parse scoped function with parameters without body.",
|
|||
})
|
||||
|
||||
PARSER_TEST("Parse scoped function with reference parameters without body.",
|
||||
PARSER_TEST_TOKENS(new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
PARSER_TEST_TOKENS(new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ColonColonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ColonColonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"baz"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "baz"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IntKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::AmpersandSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::InKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"par1"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "par1"),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CommaSymbol>(TextSpan(0, 0)),
|
||||
|
||||
|
@ -175,7 +175,7 @@ PARSER_TEST("Parse scoped function with reference parameters without body.",
|
|||
new Parser::LexTokenImpl<Parser::LexTokenKind::AmpersandSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OutKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::Whitespace>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"par2"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "par2"),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0))),
|
||||
|
@ -191,11 +191,11 @@ PARSER_TEST("Parse scoped function with reference parameters without body.",
|
|||
CHECK_FALSE(type->IsArray());
|
||||
CHECK_FALSE(type->IsHandle());
|
||||
auto& id = type->GetScopedIdentifier();
|
||||
CHECK(id.GetIdentifier().GetString() == u8"baz");
|
||||
CHECK(id.GetScope()[1].GetString() == u8"bar");
|
||||
CHECK(id.GetScope()[0].GetString() == u8"foo");
|
||||
CHECK(id.GetIdentifier().GetString() == "baz");
|
||||
CHECK(id.GetScope()[1].GetString() == "bar");
|
||||
CHECK(id.GetScope()[0].GetString() == "foo");
|
||||
CHECK_FALSE(funcStat->ReturnsReference());
|
||||
CHECK(funcStat->GetIdentifier().GetString() == u8"foobar");
|
||||
CHECK(funcStat->GetIdentifier().GetString() == "foobar");
|
||||
auto paramList = (const MalachScript::Parser::ParsedParamListStatement*)funcStat->GetParamList().get();
|
||||
CHECK(paramList->GetParameters().size() == 2);
|
||||
|
||||
|
@ -204,9 +204,9 @@ PARSER_TEST("Parse scoped function with reference parameters without body.",
|
|||
CHECK_FALSE(par1.GetTypeStatement()->IsArray());
|
||||
CHECK_FALSE(par1.GetTypeStatement()->IsHandle());
|
||||
auto& par1TypeId = par1.GetTypeStatement()->GetScopedIdentifier();
|
||||
CHECK(par1TypeId.GetIdentifier().GetString() == u8"int");
|
||||
CHECK(par1TypeId.GetIdentifier().GetString() == "int");
|
||||
CHECK(par1.GetTypeMod() == TypeMod::RefIn);
|
||||
CHECK(par1.GetIdentifier().GetString() == u8"par1");
|
||||
CHECK(par1.GetIdentifier().GetString() == "par1");
|
||||
CHECK(par1.GetDefaultExpression() == nullptr);
|
||||
|
||||
auto& par2 = *paramList->GetParameters()[1];
|
||||
|
@ -214,9 +214,9 @@ PARSER_TEST("Parse scoped function with reference parameters without body.",
|
|||
CHECK_FALSE(par2.GetTypeStatement()->IsArray());
|
||||
CHECK_FALSE(par2.GetTypeStatement()->IsHandle());
|
||||
auto& par2TypeId = par2.GetTypeStatement()->GetScopedIdentifier();
|
||||
CHECK(par2TypeId.GetIdentifier().GetString() == u8"bool");
|
||||
CHECK(par2TypeId.GetIdentifier().GetString() == "bool");
|
||||
CHECK(par2.GetTypeMod() == TypeMod::RefOut);
|
||||
CHECK(par2.GetIdentifier().GetString() == u8"par2");
|
||||
CHECK(par2.GetIdentifier().GetString() == "par2");
|
||||
CHECK(par2.GetDefaultExpression() == nullptr);
|
||||
|
||||
CHECK_FALSE(funcStat->IsConst());
|
||||
|
|
|
@ -7,9 +7,9 @@ using namespace MalachScript;
|
|||
#define PARSE_TEST(name, scriptText, asserts) \
|
||||
TEST_CASE(name) { \
|
||||
Diagnostics::Logger diags; \
|
||||
auto lexer = Parser::Lexer(u8##name, u8##scriptText, &diags); \
|
||||
auto lexer = Parser::Lexer(name, scriptText, &diags); \
|
||||
auto token = lexer.Lex(); \
|
||||
auto script = Parser::Parser::Parse(token, u8##name, &diags); \
|
||||
auto script = Parser::Parser::Parse(token, name, &diags); \
|
||||
asserts; \
|
||||
delete script; \
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ PARSE_TEST("Parse class with virtprop", "class foobar { private bool foo { get;
|
|||
REQUIRE(firstClassStatement->GetKind() == Parser::ParsedStatementKind::VirtProp);
|
||||
auto virtPropStatement = dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
|
||||
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Private);
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == u8"foo");
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
|
||||
REQUIRE(virtPropStatement->HasGet());
|
||||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
||||
|
|
|
@ -13,7 +13,7 @@ using namespace MalachScript;
|
|||
vec[i]->SetNext(vec[i + 1]); \
|
||||
} \
|
||||
Diagnostics::Logger diags; \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), "scriptname", &diags); \
|
||||
REQUIRE(diags.GetMessages().empty()); \
|
||||
asserts; \
|
||||
delete vec[0]; \
|
||||
|
@ -25,10 +25,10 @@ using namespace MalachScript;
|
|||
PARSER_TEST(
|
||||
"Parse class foobar { bool foo { get; set; } }",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
|
@ -46,7 +46,7 @@ PARSER_TEST(
|
|||
auto virtPropStatement =
|
||||
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
|
||||
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == u8"foo");
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
|
||||
REQUIRE(virtPropStatement->HasGet());
|
||||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE_FALSE(virtPropStatement->IsGetConst());
|
||||
|
@ -58,10 +58,10 @@ PARSER_TEST(
|
|||
PARSER_TEST(
|
||||
"Parse class foobar { bool foo { get const; set const; } }",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ConstKeyword>(TextSpan(0, 0)),
|
||||
|
@ -81,7 +81,7 @@ PARSER_TEST(
|
|||
auto virtPropStatement =
|
||||
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
|
||||
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == u8"foo");
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
|
||||
REQUIRE(virtPropStatement->HasGet());
|
||||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE(virtPropStatement->IsGetConst());
|
||||
|
@ -93,10 +93,10 @@ PARSER_TEST(
|
|||
PARSER_TEST(
|
||||
"Parse class foobar { bool foo { get const override; set const override; } }",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ConstKeyword>(TextSpan(0, 0)),
|
||||
|
@ -118,7 +118,7 @@ PARSER_TEST(
|
|||
auto virtPropStatement =
|
||||
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
|
||||
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == u8"foo");
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
|
||||
REQUIRE(virtPropStatement->HasGet());
|
||||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE(virtPropStatement->IsGetConst());
|
||||
|
@ -145,48 +145,47 @@ PARSER_TEST(
|
|||
|
||||
PARSER_TEST(
|
||||
"Virtprops with bodies",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"int"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
PARSER_TEST_TOKENS(
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "int"), new Parser::IdentifierToken(TextSpan(0, 0), "i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "bool"), new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::FalseKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::EqualsEqualsSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::PlusPlusSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::MinusMinusSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::EqualsEqualsSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::PlusPlusSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), "i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::MinusMinusSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
|
||||
{
|
||||
REQUIRE(script->GetStatements().size() == 1);
|
||||
auto firstStatement = script->GetStatements()[0].get();
|
||||
|
@ -197,7 +196,7 @@ PARSER_TEST(
|
|||
auto virtPropStatement =
|
||||
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
|
||||
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == u8"foo");
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
|
||||
REQUIRE(virtPropStatement->HasGet());
|
||||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE_FALSE(virtPropStatement->IsGetConst());
|
||||
|
|
Loading…
Reference in New Issue