Rework text spans a bit to include script file, make binder log an error when two classes have a circular value reference.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2021-01-09 13:20:56 +01:00
parent 8660933f27
commit 59af34fac9
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
16 changed files with 432 additions and 267 deletions

View File

@ -27,13 +27,13 @@ namespace MalachScriptRepl {
auto logger = MalachScript::Diagnostics::Logger(); auto logger = MalachScript::Diagnostics::Logger();
auto lexer = MalachScript::Parser::Lexer("diag", script, &logger); auto lexer = MalachScript::Parser::Lexer("diag", script, &logger);
const auto* firstToken = lexer.Lex(); const auto* firstToken = lexer.Lex();
const auto* parsedResult = MalachScript::Parser::Parser::Parse(firstToken, "diag", &logger); const auto* parsedResult = MalachScript::Parser::Parser::Parse(firstToken, &logger);
auto* ns = new MalachScript::Binder::BoundNamespace(); auto* ns = new MalachScript::Binder::BoundNamespace();
const MalachScript::Binder::Binder::log_func log = const MalachScript::Binder::Binder::log_func log =
[&logger](MalachScript::Diagnostics::DiagnosticLevel level, MalachScript::Diagnostics::DiagnosticType type, [&logger](MalachScript::Diagnostics::DiagnosticLevel level, MalachScript::Diagnostics::DiagnosticType type,
const MalachScript::TextSpan& span, const MalachScript::ScriptTextSpan& span,
const std::vector<std::string>& formats) { logger.Log(level, type, "", span, formats); }; const std::vector<std::string>& formats) { logger.Log(level, type, span, formats); };
MalachScript::Binder::Binder::Bind(ns, {parsedResult}, log); MalachScript::Binder::Binder::Bind(ns, {parsedResult}, log);
const MalachScript::Diagnostics::Diagnostic* diag = nullptr; const MalachScript::Diagnostics::Diagnostic* diag = nullptr;

View File

@ -66,7 +66,7 @@ namespace MalachScript::Binder {
break; break;
} }
type = new BoundType(identifier, s->GetClassAttr()); type = new BoundType(identifier, s->GetClassAttr(), s->GetSpan());
if (activeType.has_value()) { if (activeType.has_value()) {
activeType.value()->RegisterType(identifier, type.value()); activeType.value()->RegisterType(identifier, type.value());
} else { } else {
@ -210,9 +210,39 @@ namespace MalachScript::Binder {
} }
} }
static void FinaliseType(BoundType* type, std::vector<const BoundType*>& stack, const Binder::log_func& log) {
if (type->IsInitialised()) {
return;
}
if (std::find(stack.begin(), stack.end(), type) != stack.end()) {
log(Diagnostics::DiagnosticLevel::Error, Diagnostics::DiagnosticType::CircularTypeReference,
type->GetSpan().value(),
{stack[stack.size() - 1]->GetIdentifier().GetStdString(), type->GetIdentifier().GetStdString()});
return;
}
stack.push_back(type);
size_t size = 0;
for (auto& inherits : type->GetInherits()) {
if (!inherits->IsInitialised()) {
FinaliseType(const_cast<BoundType*>(inherits), stack, log);
}
size += inherits->GetSize();
}
for (auto& field : type->GetFieldsLookup()) {
if (!field.second->GetType()->IsInitialised()) {
FinaliseType(const_cast<BoundType*>(field.second->GetType()), stack, log);
}
size += field.second->GetType()->GetSize();
}
stack.pop_back();
type->Finalise(size);
}
static void FinaliseNamespace(BoundNamespace* ns, const Binder::log_func& log) { static void FinaliseNamespace(BoundNamespace* ns, const Binder::log_func& log) {
std::vector<const BoundType*> s = {};
for (const auto& t : ns->GetTypes()) { for (const auto& t : ns->GetTypes()) {
t.second->Finalise(); FinaliseType(t.second, s, log);
} }
for (const auto& n : ns->GetNamespaces()) { for (const auto& n : ns->GetNamespaces()) {
FinaliseNamespace(n.second, log); FinaliseNamespace(n.second, log);

View File

@ -10,7 +10,7 @@ namespace MalachScript::Binder {
class Binder { class Binder {
public: public:
using log_func = const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType, using log_func = const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType,
const TextSpan&, const std::vector<std::string>&)>; const ScriptTextSpan&, const std::vector<std::string>&)>;
static void Bind(BoundNamespace* ns, static void Bind(BoundNamespace* ns,
const std::vector<const MalachScript::Parser::ParsedStatement*>& statements, const std::vector<const MalachScript::Parser::ParsedStatement*>& statements,

View File

@ -1,34 +1,30 @@
#ifndef MALACHSCRIPT_BOUNDTYPE_HPP #ifndef MALACHSCRIPT_BOUNDTYPE_HPP
#define MALACHSCRIPT_BOUNDTYPE_HPP #define MALACHSCRIPT_BOUNDTYPE_HPP
#include <functional>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "../CoreData/ClassAttr.hpp"
#include "../CoreData/Identifier.hpp"
#include "../Diagnostics/Logger.hpp"
#include "BoundVariable.hpp" #include "BoundVariable.hpp"
namespace MalachScript::Binder { namespace MalachScript::Binder {
class BoundType { class BoundType {
public: public:
BoundType(Identifier identifier, ClassAttr classAttr) : _identifier(identifier), _classAttr(classAttr) {} using log_func = const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType,
BoundType(Identifier identifier, ClassAttr classAttr, size_t size) const ScriptTextSpan&, const std::vector<std::string>&)>;
: _identifier(identifier), _classAttr(classAttr), _size(size), _inherits(0) {}
inline void Finalise() noexcept { BoundType(Identifier identifier, ClassAttr classAttr, std::optional<ScriptTextSpan> span)
if (_initialised) { : _identifier(identifier), _classAttr(classAttr), _span(span) {}
return; BoundType(Identifier identifier, ClassAttr classAttr, size_t size)
} : _initialised(true), _identifier(identifier), _classAttr(classAttr), _size(size), _inherits(0) {}
void Finalise(size_t size) noexcept {
_initialised = true; _initialised = true;
for (auto& inherits : _inherits) { _size = size;
if (!inherits->IsInitialised()) {
const_cast<BoundType*>(inherits)->Finalise();
}
_size += inherits->GetSize();
}
for (auto& field : _fields) {
if (!field->GetType()->IsInitialised()) {
const_cast<BoundType*>(field->GetType())->Finalise();
}
_size += field->GetType()->GetSize();
}
} }
[[nodiscard]] inline const Identifier& GetIdentifier() const noexcept { return _identifier; } [[nodiscard]] inline const Identifier& GetIdentifier() const noexcept { return _identifier; }
[[nodiscard]] inline size_t GetSize() const noexcept { return _size; } [[nodiscard]] inline size_t GetSize() const noexcept { return _size; }
[[nodiscard]] inline bool IsInitialised() const noexcept { return _initialised; } [[nodiscard]] inline bool IsInitialised() const noexcept { return _initialised; }
@ -50,8 +46,9 @@ namespace MalachScript::Binder {
[[nodiscard]] inline const std::unordered_map<Identifier, BoundVariable*>& GetFieldsLookup() const noexcept { [[nodiscard]] inline const std::unordered_map<Identifier, BoundVariable*>& GetFieldsLookup() const noexcept {
return _fieldsLookup; return _fieldsLookup;
} }
[[nodiscard]] inline const std::vector<const BoundType*>& GetInherits() const noexcept { return _inherits; }
inline std::optional<BoundType*> ResolveType(const Identifier& identifier) const noexcept { [[nodiscard]] inline std::optional<BoundType*> ResolveType(const Identifier& identifier) const noexcept {
auto find = _types.find(identifier); auto find = _types.find(identifier);
if (find == _types.end()) { if (find == _types.end()) {
return {}; return {};
@ -59,10 +56,14 @@ namespace MalachScript::Binder {
return find->second; return find->second;
} }
[[nodiscard]] inline const std::optional<ScriptTextSpan>& GetSpan() const noexcept { return _span; }
private: private:
bool _initialised = false; bool _initialised = false;
Identifier _identifier; Identifier _identifier;
ClassAttr _classAttr; ClassAttr _classAttr;
std::optional<ScriptTextSpan> _span;
size_t _size = 0; size_t _size = 0;
std::vector<const BoundType*> _inherits; std::vector<const BoundType*> _inherits;
std::vector<BoundVariable*> _fields; std::vector<BoundVariable*> _fields;

View File

@ -1,6 +1,8 @@
#ifndef MALACHSCRIPT_BOUNDVARIABLE_HPP #ifndef MALACHSCRIPT_BOUNDVARIABLE_HPP
#define MALACHSCRIPT_BOUNDVARIABLE_HPP #define MALACHSCRIPT_BOUNDVARIABLE_HPP
#include "../CoreData/AccessModifier.hpp"
namespace MalachScript::Binder { namespace MalachScript::Binder {
class BoundType; class BoundType;

View File

@ -1,6 +1,8 @@
#ifndef MALACHSCRIPT_CLASSATTR_HPP #ifndef MALACHSCRIPT_CLASSATTR_HPP
#define MALACHSCRIPT_CLASSATTR_HPP #define MALACHSCRIPT_CLASSATTR_HPP
#include <cstdint>
namespace MalachScript { namespace MalachScript {
enum class ClassAttr : uint8_t { enum class ClassAttr : uint8_t {
None = 0, None = 0,

View File

@ -11,6 +11,7 @@ namespace MalachScript::Diagnostics {
UnknownType, UnknownType,
TypeAlreadyDefined, TypeAlreadyDefined,
CircularTypeReference,
}; };
} }

View File

@ -28,6 +28,9 @@ namespace MalachScript::Diagnostics {
return util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats()); return util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
case DiagnosticType::TypeAlreadyDefined: case DiagnosticType::TypeAlreadyDefined:
return util::Format("Type already defined: '{0}'", diag->GetFormats()); return util::Format("Type already defined: '{0}'", diag->GetFormats());
case DiagnosticType::CircularTypeReference:
return util::Format("Type '{0}' can't hold a value type of type '{1}' due to a circular reference",
diag->GetFormats());
} }
return std::to_string((uint8_t)diag->GetType()); return std::to_string((uint8_t)diag->GetType());
} }

View File

@ -9,25 +9,29 @@ namespace MalachScript::Diagnostics {
std::vector<Diagnostic> _messages; std::vector<Diagnostic> _messages;
public: public:
inline void Log(DiagnosticLevel level, DiagnosticType type, std::string_view scriptName, TextSpan span, inline void Log(DiagnosticLevel level, DiagnosticType type, const ScriptTextSpan& span,
const std::vector<std::string>& formats = {}) { const std::vector<std::string>& formats = {}) {
_messages.emplace_back(level, type, scriptName, span, formats); _messages.emplace_back(level, type, span.GetScriptName(), span.GetSpan(), formats);
} }
inline void LogTrace(DiagnosticType type, std::string_view scriptName, TextSpan span) { inline void LogTrace(DiagnosticType type, const ScriptTextSpan& span,
Log(DiagnosticLevel::Trace, type, scriptName, span);
}
inline void LogInfo(DiagnosticType type, std::string_view scriptName, TextSpan span) {
Log(DiagnosticLevel::Information, type, scriptName, span);
}
inline void LogWarning(DiagnosticType type, std::string_view scriptName, TextSpan span) {
Log(DiagnosticLevel::Warning, type, scriptName, span);
}
inline void LogError(DiagnosticType type, std::string_view scriptName, TextSpan span,
const std::vector<std::string>& formats = {}) { const std::vector<std::string>& formats = {}) {
Log(DiagnosticLevel::Error, type, scriptName, span, formats); Log(DiagnosticLevel::Trace, type, span, formats);
} }
inline void LogCritical(DiagnosticType type, std::string_view scriptName, TextSpan span) { inline void LogInfo(DiagnosticType type, const ScriptTextSpan& span,
Log(DiagnosticLevel::Critical, type, scriptName, span); const std::vector<std::string>& formats = {}) {
Log(DiagnosticLevel::Information, type, span, formats);
}
inline void LogWarning(DiagnosticType type, const ScriptTextSpan& span,
const std::vector<std::string>& formats = {}) {
Log(DiagnosticLevel::Warning, type, span, formats);
}
inline void LogError(DiagnosticType type, const ScriptTextSpan& span,
const std::vector<std::string>& formats = {}) {
Log(DiagnosticLevel::Error, type, span, formats);
}
inline void LogCritical(DiagnosticType type, const ScriptTextSpan& span,
const std::vector<std::string>& formats = {}) {
Log(DiagnosticLevel::Critical, type, span, formats);
} }
[[nodiscard]] const std::vector<Diagnostic>& GetMessages() const noexcept { return _messages; } [[nodiscard]] const std::vector<Diagnostic>& GetMessages() const noexcept { return _messages; }

View File

@ -11,14 +11,14 @@
namespace MalachScript::Parser { namespace MalachScript::Parser {
class LexToken { class LexToken {
std::unique_ptr<const LexToken> _next; std::unique_ptr<const LexToken> _next;
TextSpan _span; ScriptTextSpan _span;
public: public:
inline LexToken(const TextSpan& span) : _span(span) {} inline LexToken(const ScriptTextSpan& span) : _span(span) {}
virtual ~LexToken() = default; virtual ~LexToken() = default;
[[nodiscard]] virtual LexTokenKind GetKind() const noexcept = 0; [[nodiscard]] virtual LexTokenKind GetKind() const noexcept = 0;
[[nodiscard]] inline const std::unique_ptr<const LexToken>& GetNext() const noexcept { return _next; } [[nodiscard]] inline const std::unique_ptr<const LexToken>& GetNext() const noexcept { return _next; }
[[nodiscard]] inline const TextSpan& GetSpan() const noexcept { return _span; } [[nodiscard]] inline const ScriptTextSpan& GetSpan() const noexcept { return _span; }
[[nodiscard]] virtual std::string ToString() const noexcept { return LexTokenKindHelper::ToString(GetKind()); } [[nodiscard]] virtual std::string ToString() const noexcept { return LexTokenKindHelper::ToString(GetKind()); }
inline void SetNext(LexToken* token) { _next = std::unique_ptr<const LexToken>(token); } inline void SetNext(LexToken* token) { _next = std::unique_ptr<const LexToken>(token); }
@ -26,7 +26,7 @@ namespace MalachScript::Parser {
template <LexTokenKind kind> class LexTokenImpl : public LexToken { template <LexTokenKind kind> class LexTokenImpl : public LexToken {
public: public:
inline LexTokenImpl(const TextSpan& span) : LexToken(span){}; inline LexTokenImpl(const ScriptTextSpan& span) : LexToken(span){};
[[nodiscard]] inline LexTokenKind GetKind() const noexcept final { return kind; } [[nodiscard]] inline LexTokenKind GetKind() const noexcept final { return kind; }
}; };
@ -34,7 +34,7 @@ namespace MalachScript::Parser {
ParseInt _value; ParseInt _value;
public: public:
IntegerLiteral(const TextSpan& span, ParseInt value) IntegerLiteral(const ScriptTextSpan& span, ParseInt value)
: LexTokenImpl<LexTokenKind::IntegerLiteral>(span), _value(value) {} : LexTokenImpl<LexTokenKind::IntegerLiteral>(span), _value(value) {}
[[nodiscard]] inline ParseInt GetValue() const noexcept { return _value; } [[nodiscard]] inline ParseInt GetValue() const noexcept { return _value; }
@ -49,7 +49,7 @@ namespace MalachScript::Parser {
ParseFloat _value; ParseFloat _value;
public: public:
FloatLiteral(const TextSpan& span, ParseFloat value) FloatLiteral(const ScriptTextSpan& span, ParseFloat value)
: LexTokenImpl<LexTokenKind::FloatLiteral>(span), _value(value) {} : LexTokenImpl<LexTokenKind::FloatLiteral>(span), _value(value) {}
[[nodiscard]] inline long double GetValue() const noexcept { return _value; } [[nodiscard]] inline long double GetValue() const noexcept { return _value; }
@ -64,7 +64,7 @@ namespace MalachScript::Parser {
ParseString _value; ParseString _value;
public: public:
StringLiteral(const TextSpan& span, ParseString value) StringLiteral(const ScriptTextSpan& span, ParseString value)
: LexTokenImpl<LexTokenKind::StringLiteral>(span), _value(std::move(value)) {} : LexTokenImpl<LexTokenKind::StringLiteral>(span), _value(std::move(value)) {}
[[nodiscard]] inline const ParseString& GetValue() const noexcept { return _value; } [[nodiscard]] inline const ParseString& GetValue() const noexcept { return _value; }
@ -81,7 +81,7 @@ namespace MalachScript::Parser {
Identifier _value; Identifier _value;
public: public:
IdentifierToken(const TextSpan& span, Identifier value) IdentifierToken(const ScriptTextSpan& span, Identifier value)
: LexTokenImpl<LexTokenKind::Identifier>(span), _value(value) {} : LexTokenImpl<LexTokenKind::Identifier>(span), _value(value) {}
[[nodiscard]] inline const Identifier& GetValue() const noexcept { return _value; } [[nodiscard]] inline const Identifier& GetValue() const noexcept { return _value; }

View File

@ -25,7 +25,8 @@ namespace MalachScript::Parser {
auto start = _position; auto start = _position;
auto c = Consume(); auto c = Consume();
switch (c) { switch (c) {
case '\0': return Create<LexTokenImpl<LexTokenKind::EndOfFile>>(TextSpan(start + 1, start + 2)); case '\0':
return Create<LexTokenImpl<LexTokenKind::EndOfFile>>(ScriptTextSpan(start + 1, start + 2, _scriptName));
case '*': { case '*': {
auto n = Peek(); auto n = Peek();
if (n == '*') { if (n == '*') {
@ -34,71 +35,81 @@ namespace MalachScript::Parser {
if (n == '=') { if (n == '=') {
Progress(); Progress();
// **= // **=
return Create<LexTokenImpl<LexTokenKind::StarStarEqualsSymbol>>(TextSpan(start, start + 3)); return Create<LexTokenImpl<LexTokenKind::StarStarEqualsSymbol>>(
ScriptTextSpan(start, start + 3, _scriptName));
} }
// ** // **
return Create<LexTokenImpl<LexTokenKind::StarStarSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::StarStarSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '=') { if (n == '=') {
Progress(); Progress();
// *= // *=
return Create<LexTokenImpl<LexTokenKind::StarEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::StarEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// * // *
return Create<LexTokenImpl<LexTokenKind::StarSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::StarSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '/': case '/':
if (Peek() == '=') { if (Peek() == '=') {
Progress(); Progress();
// /= // /=
return Create<LexTokenImpl<LexTokenKind::SlashEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::SlashEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// / // /
return Create<LexTokenImpl<LexTokenKind::SlashSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::SlashSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '%': case '%':
if (Peek() == '=') { if (Peek() == '=') {
Progress(); Progress();
// %= // %=
return Create<LexTokenImpl<LexTokenKind::PercentEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::PercentEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// % // %
return Create<LexTokenImpl<LexTokenKind::PercentSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::PercentSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '+': { case '+': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// += // +=
return Create<LexTokenImpl<LexTokenKind::PlusEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::PlusEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '+') { if (n == '+') {
Progress(); Progress();
// ++ // ++
return Create<LexTokenImpl<LexTokenKind::PlusPlusSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::PlusPlusSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// + // +
return Create<LexTokenImpl<LexTokenKind::PlusSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::PlusSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '-': { case '-': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// -= // -=
return Create<LexTokenImpl<LexTokenKind::MinusEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::MinusEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '-') { if (n == '-') {
Progress(); Progress();
// -- // --
return Create<LexTokenImpl<LexTokenKind::MinusMinusSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::MinusMinusSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// - // -
return Create<LexTokenImpl<LexTokenKind::MinusSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::MinusSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '<': { case '<': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// <= // <=
return Create<LexTokenImpl<LexTokenKind::LessThanEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::LessThanEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '<') { if (n == '<') {
Progress(); Progress();
@ -106,20 +117,23 @@ namespace MalachScript::Parser {
Progress(); Progress();
// <<= // <<=
return Create<LexTokenImpl<LexTokenKind::LessThanLessThanEqualsSymbol>>( return Create<LexTokenImpl<LexTokenKind::LessThanLessThanEqualsSymbol>>(
TextSpan(start, start + 3)); ScriptTextSpan(start, start + 3, _scriptName));
} }
// << // <<
return Create<LexTokenImpl<LexTokenKind::LessThanLessThanSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::LessThanLessThanSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// < // <
return Create<LexTokenImpl<LexTokenKind::LessThanSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::LessThanSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
} }
case '>': { case '>': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// >= // >=
return Create<LexTokenImpl<LexTokenKind::GreaterThanEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::GreaterThanEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '>') { if (n == '>') {
Progress(); Progress();
@ -128,7 +142,7 @@ namespace MalachScript::Parser {
Progress(); Progress();
// >>= // >>=
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanEqualsSymbol>>( return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanEqualsSymbol>>(
TextSpan(start, start + 3)); ScriptTextSpan(start, start + 3, _scriptName));
} }
if (n == '>') { if (n == '>') {
Progress(); Progress();
@ -136,125 +150,159 @@ namespace MalachScript::Parser {
Progress(); Progress();
// >>>= // >>>=
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol>>( return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol>>(
TextSpan(start, start + 4)); ScriptTextSpan(start, start + 4, _scriptName));
} }
// >>> // >>>
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanGreaterThanSymbol>>( return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanGreaterThanSymbol>>(
TextSpan(start, start + 3)); ScriptTextSpan(start, start + 3, _scriptName));
} }
// >> // >>
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// > // >
return Create<LexTokenImpl<LexTokenKind::GreaterThanSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::GreaterThanSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
} }
case '(': return Create<LexTokenImpl<LexTokenKind::OpenParenthesisSymbol>>(TextSpan(start, start + 1)); case '(':
case ')': return Create<LexTokenImpl<LexTokenKind::CloseParenthesisSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::OpenParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case ')':
return Create<LexTokenImpl<LexTokenKind::CloseParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '=': { case '=': {
if (Peek() == '=') { if (Peek() == '=') {
Progress(); Progress();
// == // ==
return Create<LexTokenImpl<LexTokenKind::EqualsEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::EqualsEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// = // =
return Create<LexTokenImpl<LexTokenKind::EqualsSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::EqualsSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '!': { case '!': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// != // !=
return Create<LexTokenImpl<LexTokenKind::ExclamationMarkEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::ExclamationMarkEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == 'i' && Peek(2) == 's') { if (n == 'i' && Peek(2) == 's') {
Progress(2); Progress(2);
// !is // !is
return Create<LexTokenImpl<LexTokenKind::ExclamationMarkIsSymbol>>(TextSpan(start, start + 3)); return Create<LexTokenImpl<LexTokenKind::ExclamationMarkIsSymbol>>(
ScriptTextSpan(start, start + 3, _scriptName));
} }
// ! // !
return Create<LexTokenImpl<LexTokenKind::ExclamationMarkSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::ExclamationMarkSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
} }
case '?': return Create<LexTokenImpl<LexTokenKind::QuestionMarkSymbol>>(TextSpan(start, start + 1)); case '?':
return Create<LexTokenImpl<LexTokenKind::QuestionMarkSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case ':': { case ':': {
if (Peek() == ':') { if (Peek() == ':') {
Progress(); Progress();
// :: // ::
return Create<LexTokenImpl<LexTokenKind::ColonColonSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::ColonColonSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// : // :
return Create<LexTokenImpl<LexTokenKind::ColonSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::ColonSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '&': { case '&': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// &= // &=
return Create<LexTokenImpl<LexTokenKind::AmpersandEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::AmpersandEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '&') { if (n == '&') {
Progress(); Progress();
// && // &&
return Create<LexTokenImpl<LexTokenKind::AmpersandAmpersandSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::AmpersandAmpersandSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// & // &
return Create<LexTokenImpl<LexTokenKind::AmpersandSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::AmpersandSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
} }
case ',': return Create<LexTokenImpl<LexTokenKind::CommaSymbol>>(TextSpan(start, start + 1)); case ',':
case '{': return Create<LexTokenImpl<LexTokenKind::OpenCurlyParenthesisSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::CommaSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '{':
return Create<LexTokenImpl<LexTokenKind::OpenCurlyParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '}': case '}':
return Create<LexTokenImpl<LexTokenKind::CloseCurlyParenthesisSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::CloseCurlyParenthesisSymbol>>(
case ';': return Create<LexTokenImpl<LexTokenKind::SemicolonSymbol>>(TextSpan(start, start + 1)); ScriptTextSpan(start, start + 1, _scriptName));
case ';':
return Create<LexTokenImpl<LexTokenKind::SemicolonSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '|': { case '|': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// |= // |=
return Create<LexTokenImpl<LexTokenKind::VerticalLineEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::VerticalLineEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '|') { if (n == '|') {
Progress(); Progress();
// || // ||
return Create<LexTokenImpl<LexTokenKind::VerticalLineVerticalLineSymbol>>( return Create<LexTokenImpl<LexTokenKind::VerticalLineVerticalLineSymbol>>(
TextSpan(start, start + 2)); ScriptTextSpan(start, start + 2, _scriptName));
} }
// | // |
return Create<LexTokenImpl<LexTokenKind::VerticalLineSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::VerticalLineSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
} }
case '^': { case '^': {
auto n = Peek(); auto n = Peek();
if (n == '=') { if (n == '=') {
Progress(); Progress();
// ^= // ^=
return Create<LexTokenImpl<LexTokenKind::CaretEqualsSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::CaretEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
if (n == '^') { if (n == '^') {
Progress(); Progress();
// ^^ // ^^
return Create<LexTokenImpl<LexTokenKind::CaretCaretSymbol>>(TextSpan(start, start + 2)); return Create<LexTokenImpl<LexTokenKind::CaretCaretSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
} }
// ^ // ^
return Create<LexTokenImpl<LexTokenKind::CaretSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::CaretSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '~': return Create<LexTokenImpl<LexTokenKind::TildeSymbol>>(TextSpan(start, start + 1)); case '~':
case '.': return Create<LexTokenImpl<LexTokenKind::DotSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::TildeSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '[': return Create<LexTokenImpl<LexTokenKind::OpenBlockParenthesisSymbol>>(TextSpan(start, start + 1)); case '.':
return Create<LexTokenImpl<LexTokenKind::DotSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '[':
return Create<LexTokenImpl<LexTokenKind::OpenBlockParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case ']': case ']':
return Create<LexTokenImpl<LexTokenKind::CloseBlockParenthesisSymbol>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::CloseBlockParenthesisSymbol>>(
case '@': return Create<LexTokenImpl<LexTokenKind::AtSymbol>>(TextSpan(start, start + 1)); ScriptTextSpan(start, start + 1, _scriptName));
case '@':
return Create<LexTokenImpl<LexTokenKind::AtSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case ' ': case ' ':
case '\r': case '\r':
case '\n': case '\n':
case '\t': return Create<LexTokenImpl<LexTokenKind::Whitespace>>(TextSpan(start, start + 1)); case '\t':
return Create<LexTokenImpl<LexTokenKind::Whitespace>>(ScriptTextSpan(start, start + 1, _scriptName));
// Byte order mark // Byte order mark
case '\xEF': { case '\xEF': {
if (Peek() == '\xBB' && Peek(2) == '\xBF') { if (Peek() == '\xBB' && Peek(2) == '\xBF') {
Progress(2); Progress(2);
return Create<LexTokenImpl<LexTokenKind::Whitespace>>(TextSpan(start, start + 3)); return Create<LexTokenImpl<LexTokenKind::Whitespace>>(
ScriptTextSpan(start, start + 3, _scriptName));
} }
LogError(Diagnostics::DiagnosticType::UnknownCharacter, TextSpan(start, start + 1), LogError(Diagnostics::DiagnosticType::UnknownCharacter, ScriptTextSpan(start, start + 1, _scriptName),
{std::string(1, c)}); {std::string(1, c)});
return Create<LexTokenImpl<LexTokenKind::Unknown>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::Unknown>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
case '0': case '0':
case '1': case '1':
@ -277,9 +325,9 @@ namespace MalachScript::Parser {
default: default:
if (IsAlphaNumericalOrUnderscore(c)) if (IsAlphaNumericalOrUnderscore(c))
return LexKeywordOrIdentifier(); return LexKeywordOrIdentifier();
LogError(Diagnostics::DiagnosticType::UnknownCharacter, TextSpan(start, start + 1), LogError(Diagnostics::DiagnosticType::UnknownCharacter, ScriptTextSpan(start, start + 1, _scriptName),
{std::string(1, (char)c)}); {std::string(1, (char)c)});
return Create<LexTokenImpl<LexTokenKind::Unknown>>(TextSpan(start, start + 1)); return Create<LexTokenImpl<LexTokenKind::Unknown>>(ScriptTextSpan(start, start + 1, _scriptName));
} }
} }
@ -311,7 +359,7 @@ namespace MalachScript::Parser {
Progress(); Progress();
numericalSystem = 2; numericalSystem = 2;
break; break;
default: return Create<IntegerLiteral>(TextSpan(_position - 1, _position), 0); default: return Create<IntegerLiteral>(ScriptTextSpan(_position - 1, _position, _scriptName), 0);
} }
} }
} }
@ -390,9 +438,9 @@ namespace MalachScript::Parser {
if (isExponent) { if (isExponent) {
val *= pow(10, exponentValue); val *= pow(10, exponentValue);
} }
return Create<FloatLiteral>(TextSpan(start, _position), val); return Create<FloatLiteral>(ScriptTextSpan(start, _position, _scriptName), val);
} }
return Create<IntegerLiteral>(TextSpan(start, _position), value); return Create<IntegerLiteral>(ScriptTextSpan(start, _position, _scriptName), value);
} }
IntegerLiteral* Lexer::LexHexadecimal() { IntegerLiteral* Lexer::LexHexadecimal() {
@ -407,7 +455,7 @@ namespace MalachScript::Parser {
value <<= 4; value <<= 4;
value += v; value += v;
} }
return Create<IntegerLiteral>(TextSpan(start - 1, _position), value); return Create<IntegerLiteral>(ScriptTextSpan(start - 1, _position, _scriptName), value);
} }
IntegerLiteral* Lexer::LexOctal() { IntegerLiteral* Lexer::LexOctal() {
auto start = _position; auto start = _position;
@ -421,7 +469,7 @@ namespace MalachScript::Parser {
value <<= 3; value <<= 3;
value += v; value += v;
} }
return Create<IntegerLiteral>(TextSpan(start - 1, _position), value); return Create<IntegerLiteral>(ScriptTextSpan(start - 1, _position, _scriptName), value);
} }
IntegerLiteral* Lexer::LexBinary() { IntegerLiteral* Lexer::LexBinary() {
auto start = _position; auto start = _position;
@ -435,7 +483,7 @@ namespace MalachScript::Parser {
value <<= 1; value <<= 1;
value += v; value += v;
} }
return Create<IntegerLiteral>(TextSpan(start - 1, _position), value); return Create<IntegerLiteral>(ScriptTextSpan(start - 1, _position, _scriptName), value);
} }
StringLiteral* Lexer::LexString(char opening, bool heredoc) { StringLiteral* Lexer::LexString(char opening, bool heredoc) {
auto openingPos = _position; auto openingPos = _position;
@ -455,13 +503,13 @@ namespace MalachScript::Parser {
break; break;
} }
if (current == '\0') { if (current == '\0') {
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString, TextSpan(start, start + offset), LogError(Diagnostics::DiagnosticType::ExpectedEndOfString,
{"EndOfFile"}); ScriptTextSpan(start, start + offset, _scriptName), {"EndOfFile"});
break; break;
} }
if (!heredoc && (current == '\n' || current == '\r')) { if (!heredoc && (current == '\n' || current == '\r')) {
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString, TextSpan(start, start + offset), LogError(Diagnostics::DiagnosticType::ExpectedEndOfString,
{"Newline"}); ScriptTextSpan(start, start + offset, _scriptName), {"Newline"});
break; break;
} }
offset++; offset++;
@ -470,7 +518,7 @@ namespace MalachScript::Parser {
if (heredoc) { if (heredoc) {
Progress(2); Progress(2);
} }
return Create<StringLiteral>(TextSpan(openingPos, openingPos + _position), return Create<StringLiteral>(ScriptTextSpan(openingPos, openingPos + _position, _scriptName),
ParseString(_script.substr(start, offset))); ParseString(_script.substr(start, offset)));
} }
@ -485,135 +533,151 @@ namespace MalachScript::Parser {
auto hash = Identifier::Hash(str); auto hash = Identifier::Hash(str);
switch (hash) { switch (hash) {
case Identifier::Hash("and"): case Identifier::Hash("and"):
return Create<LexTokenImpl<LexTokenKind::AndKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::AndKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("abstract"): case Identifier::Hash("abstract"):
return Create<LexTokenImpl<LexTokenKind::AbstractKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::AbstractKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("auto"): case Identifier::Hash("auto"):
return Create<LexTokenImpl<LexTokenKind::AutoKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::AutoKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("bool"): case Identifier::Hash("bool"):
return Create<LexTokenImpl<LexTokenKind::BoolKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::BoolKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("break"): case Identifier::Hash("break"):
return Create<LexTokenImpl<LexTokenKind::BreakKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::BreakKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("case"): case Identifier::Hash("case"):
return Create<LexTokenImpl<LexTokenKind::CaseKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::CaseKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("cast"): case Identifier::Hash("cast"):
return Create<LexTokenImpl<LexTokenKind::CastKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::CastKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("catch"): case Identifier::Hash("catch"):
return Create<LexTokenImpl<LexTokenKind::CatchKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::CatchKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("class"): case Identifier::Hash("class"):
return Create<LexTokenImpl<LexTokenKind::ClassKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ClassKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("const"): case Identifier::Hash("const"):
return Create<LexTokenImpl<LexTokenKind::ConstKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ConstKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("continue"): case Identifier::Hash("continue"):
return Create<LexTokenImpl<LexTokenKind::ContinueKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ContinueKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("default"): case Identifier::Hash("default"):
return Create<LexTokenImpl<LexTokenKind::DefaultKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::DefaultKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("do"): case Identifier::Hash("do"):
return Create<LexTokenImpl<LexTokenKind::DoKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::DoKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("double"): case Identifier::Hash("double"):
return Create<LexTokenImpl<LexTokenKind::DoubleKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::DoubleKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("else"): case Identifier::Hash("else"):
return Create<LexTokenImpl<LexTokenKind::ElseKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ElseKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("enum"): case Identifier::Hash("enum"):
return Create<LexTokenImpl<LexTokenKind::EnumKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::EnumKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("explicit"): case Identifier::Hash("explicit"):
return Create<LexTokenImpl<LexTokenKind::ExplicitKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ExplicitKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("external"): case Identifier::Hash("external"):
return Create<LexTokenImpl<LexTokenKind::ExternalKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ExternalKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("false"): case Identifier::Hash("false"):
return Create<LexTokenImpl<LexTokenKind::FalseKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::FalseKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("final"): case Identifier::Hash("final"):
return Create<LexTokenImpl<LexTokenKind::FinalKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::FinalKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("float"): case Identifier::Hash("float"):
return Create<LexTokenImpl<LexTokenKind::FloatKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::FloatKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("for"): case Identifier::Hash("for"):
return Create<LexTokenImpl<LexTokenKind::ForKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ForKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("from"): case Identifier::Hash("from"):
return Create<LexTokenImpl<LexTokenKind::FromKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::FromKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("funcdef"): case Identifier::Hash("funcdef"):
return Create<LexTokenImpl<LexTokenKind::FuncdefKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::FuncdefKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("function"): case Identifier::Hash("function"):
return Create<LexTokenImpl<LexTokenKind::FunctionKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::FunctionKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("get"): case Identifier::Hash("get"):
return Create<LexTokenImpl<LexTokenKind::GetKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::GetKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("if"): case Identifier::Hash("if"):
return Create<LexTokenImpl<LexTokenKind::IfKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::IfKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("import"): case Identifier::Hash("import"):
return Create<LexTokenImpl<LexTokenKind::ImportKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ImportKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("in"): case Identifier::Hash("in"):
return Create<LexTokenImpl<LexTokenKind::InKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::InKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("inout"): case Identifier::Hash("inout"):
return Create<LexTokenImpl<LexTokenKind::InoutKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::InoutKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("int"): case Identifier::Hash("int"):
return Create<LexTokenImpl<LexTokenKind::IntKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::IntKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("interface"): case Identifier::Hash("interface"):
return Create<LexTokenImpl<LexTokenKind::InterfaceKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::InterfaceKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("int8"): case Identifier::Hash("int8"):
return Create<LexTokenImpl<LexTokenKind::Int8Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Int8Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("int16"): case Identifier::Hash("int16"):
return Create<LexTokenImpl<LexTokenKind::Int16Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Int16Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("int32"): case Identifier::Hash("int32"):
return Create<LexTokenImpl<LexTokenKind::Int32Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Int32Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("int64"): case Identifier::Hash("int64"):
return Create<LexTokenImpl<LexTokenKind::Int64Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Int64Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("is"): case Identifier::Hash("is"):
return Create<LexTokenImpl<LexTokenKind::IsKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::IsKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("mixin"): case Identifier::Hash("mixin"):
return Create<LexTokenImpl<LexTokenKind::MixinKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::MixinKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("namespace"): case Identifier::Hash("namespace"):
return Create<LexTokenImpl<LexTokenKind::NamespaceKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::NamespaceKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("not"): case Identifier::Hash("not"):
return Create<LexTokenImpl<LexTokenKind::NotKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::NotKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("null"): case Identifier::Hash("null"):
return Create<LexTokenImpl<LexTokenKind::NullKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::NullKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("or"): case Identifier::Hash("or"):
return Create<LexTokenImpl<LexTokenKind::OrKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::OrKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("out"): case Identifier::Hash("out"):
return Create<LexTokenImpl<LexTokenKind::OutKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::OutKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("override"): case Identifier::Hash("override"):
return Create<LexTokenImpl<LexTokenKind::OverrideKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::OverrideKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("private"): case Identifier::Hash("private"):
return Create<LexTokenImpl<LexTokenKind::PrivateKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::PrivateKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("property"): case Identifier::Hash("property"):
return Create<LexTokenImpl<LexTokenKind::PropertyKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::PropertyKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("protected"): case Identifier::Hash("protected"):
return Create<LexTokenImpl<LexTokenKind::ProtectedKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ProtectedKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("return"): case Identifier::Hash("return"):
return Create<LexTokenImpl<LexTokenKind::ReturnKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ReturnKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("set"): case Identifier::Hash("set"):
return Create<LexTokenImpl<LexTokenKind::SetKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::SetKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("shared"): case Identifier::Hash("shared"):
return Create<LexTokenImpl<LexTokenKind::SharedKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::SharedKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("super"): case Identifier::Hash("super"):
return Create<LexTokenImpl<LexTokenKind::SuperKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::SuperKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("switch"): case Identifier::Hash("switch"):
return Create<LexTokenImpl<LexTokenKind::SwitchKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::SwitchKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("this"): case Identifier::Hash("this"):
return Create<LexTokenImpl<LexTokenKind::ThisKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::ThisKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("true"): case Identifier::Hash("true"):
return Create<LexTokenImpl<LexTokenKind::TrueKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::TrueKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("try"): case Identifier::Hash("try"):
return Create<LexTokenImpl<LexTokenKind::TryKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::TryKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("typedef"): case Identifier::Hash("typedef"):
return Create<LexTokenImpl<LexTokenKind::TypedefKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::TypedefKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("uint"): case Identifier::Hash("uint"):
return Create<LexTokenImpl<LexTokenKind::UintKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::UintKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("uint8"): case Identifier::Hash("uint8"):
return Create<LexTokenImpl<LexTokenKind::Uint8Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Uint8Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("uint16"): case Identifier::Hash("uint16"):
return Create<LexTokenImpl<LexTokenKind::Uint16Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Uint16Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("uint32"): case Identifier::Hash("uint32"):
return Create<LexTokenImpl<LexTokenKind::Uint32Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Uint32Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("uint64"): case Identifier::Hash("uint64"):
return Create<LexTokenImpl<LexTokenKind::Uint64Keyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::Uint64Keyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("void"): case Identifier::Hash("void"):
return Create<LexTokenImpl<LexTokenKind::VoidKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::VoidKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("while"): case Identifier::Hash("while"):
return Create<LexTokenImpl<LexTokenKind::WhileKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::WhileKeyword>>(ScriptTextSpan(start, _position, _scriptName));
case Identifier::Hash("xor"): case Identifier::Hash("xor"):
return Create<LexTokenImpl<LexTokenKind::XorKeyword>>(TextSpan(start, _position)); return Create<LexTokenImpl<LexTokenKind::XorKeyword>>(ScriptTextSpan(start, _position, _scriptName));
default: return Create<IdentifierToken>(TextSpan(start, _position), Identifier(str.data(), offset, hash)); default:
return Create<IdentifierToken>(ScriptTextSpan(start, _position, _scriptName),
Identifier(str.data(), offset, hash));
} }
} }
bool Lexer::IsAlphaNumericalOrUnderscore(char c) { bool Lexer::IsAlphaNumericalOrUnderscore(char c) {

View File

@ -57,8 +57,9 @@ namespace MalachScript::Parser {
return _allocator.Create<T>(args...); return _allocator.Create<T>(args...);
} }
inline void LogError(Diagnostics::DiagnosticType type, TextSpan span, const std::vector<std::string>& formats) { inline void LogError(Diagnostics::DiagnosticType type, const ScriptTextSpan& span,
_diagnostics->LogError(type, _scriptName, span, formats); const std::vector<std::string>& formats) {
_diagnostics->LogError(type, span, formats);
} }
}; };
} }

View File

@ -38,11 +38,10 @@
namespace MalachScript::Parser { namespace MalachScript::Parser {
using namespace Diagnostics; using namespace Diagnostics;
const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, std::string_view scriptName, const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, Logger* diagnostics) {
Logger* diagnostics) { const log_func& log = [diagnostics](DiagnosticLevel level, DiagnosticType type, const ScriptTextSpan& span,
const log_func& log = [diagnostics, scriptName](DiagnosticLevel level, DiagnosticType type, const std::vector<std::string>& formats) {
const TextSpan& span, const std::vector<std::string>& formats) { diagnostics->Log(level, type, span, formats);
diagnostics->Log(level, type, scriptName, span, formats);
}; };
ScopedPtr<const ParsedStatement> s = nullptr; ScopedPtr<const ParsedStatement> s = nullptr;
@ -89,7 +88,7 @@ namespace MalachScript::Parser {
if (currentAmount > 0) { if (currentAmount > 0) {
end = statements.back()->GetSpan().GetEnd(); end = statements.back()->GetSpan().GetEnd();
} }
out = new ParsedScriptStatement(TextSpan(0, end), statements); out = new ParsedScriptStatement(ScriptTextSpan(0, end, currentToken->GetSpan().GetScriptName()), statements);
currentToken = current; currentToken = current;
return true; return true;
} }
@ -172,8 +171,9 @@ namespace MalachScript::Parser {
logUnexpectedTokenWithAnyOf(current, LexTokenKind::SemicolonSymbol, LexTokenKind::ColonSymbol, logUnexpectedTokenWithAnyOf(current, LexTokenKind::SemicolonSymbol, LexTokenKind::ColonSymbol,
LexTokenKind::OpenCurlyParenthesisSymbol); LexTokenKind::OpenCurlyParenthesisSymbol);
} }
out = new ParsedClassStatement(TextSpan(start, current->GetSpan().GetEnd()), classAttr, identifier, inherits, out = new ParsedClassStatement(
body); ScriptTextSpan(start, current->GetSpan().GetEnd(), current->GetSpan().GetScriptName()), classAttr,
identifier, inherits, body);
currentToken = current; currentToken = current;
return true; return true;
} }
@ -197,7 +197,9 @@ namespace MalachScript::Parser {
} }
PROGRESS_TOKEN(current); PROGRESS_TOKEN(current);
EXPECT_TOKEN(current, SemicolonSymbol); EXPECT_TOKEN(current, SemicolonSymbol);
out = new ParsedTypeDefStatement(TextSpan(start, current->GetSpan().GetEnd()), defineFrom, defineTo); out = new ParsedTypeDefStatement(
ScriptTextSpan(start, current->GetSpan().GetEnd(), current->GetSpan().GetScriptName()), defineFrom,
defineTo);
return true; return true;
} }
bool Parser::ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, bool Parser::ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
@ -221,7 +223,7 @@ namespace MalachScript::Parser {
} }
auto end = current->GetSpan().GetEnd(); auto end = current->GetSpan().GetEnd();
EXPECT_TOKEN(current, CloseCurlyParenthesisSymbol); EXPECT_TOKEN(current, CloseCurlyParenthesisSymbol);
out = new ParsedNamespaceStatement(TextSpan(start, end), identifier, out = new ParsedNamespaceStatement(ScriptTextSpan(start, end, current->GetSpan().GetScriptName()), identifier,
(const ParsedScriptStatement*)script.TakeOwnership()); (const ParsedScriptStatement*)script.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
@ -289,9 +291,10 @@ namespace MalachScript::Parser {
} else { } else {
PROGRESS_TOKEN(current); PROGRESS_TOKEN(current);
} }
out = new ParsedFuncStatement(TextSpan(start, current->GetSpan().GetEnd()), isShared, isExternal, out = new ParsedFuncStatement(
accessModifier, typeStatement.TakeOwnership(), returnsReference, identifier, ScriptTextSpan(start, current->GetSpan().GetEnd(), current->GetSpan().GetScriptName()), isShared,
paramList.TakeOwnership(), isConst, funcAttr, statblock.TakeOwnership()); isExternal, accessModifier, typeStatement.TakeOwnership(), returnsReference, identifier,
paramList.TakeOwnership(), isConst, funcAttr, statblock.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
} }
@ -331,7 +334,8 @@ namespace MalachScript::Parser {
} }
auto end = current->GetSpan().GetEnd(); auto end = current->GetSpan().GetEnd();
currentToken = current; currentToken = current;
out = new ParsedTypeStatement(TextSpan(start, end), isConst, isArray, isHandle, scopedIdentifier); out = new ParsedTypeStatement(ScriptTextSpan(start, end, current->GetSpan().GetScriptName()), isConst, isArray,
isHandle, scopedIdentifier);
return true; return true;
} }
bool Parser::ParseScope(std::vector<Identifier>& scope, const LexToken*& currentToken, const log_func& log) { bool Parser::ParseScope(std::vector<Identifier>& scope, const LexToken*& currentToken, const log_func& log) {
@ -413,11 +417,15 @@ namespace MalachScript::Parser {
if (currentToken->GetKind() == LexTokenKind::VoidKeyword) { if (currentToken->GetKind() == LexTokenKind::VoidKeyword) {
PROGRESS_TOKEN(currentToken); PROGRESS_TOKEN(currentToken);
EXPECT_TOKEN(currentToken, CloseParenthesisSymbol); EXPECT_TOKEN(currentToken, CloseParenthesisSymbol);
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters); out = new ParsedParamListStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()),
parameters);
return true; return true;
} }
if (currentToken->GetKind() == LexTokenKind::CloseParenthesisSymbol) { if (currentToken->GetKind() == LexTokenKind::CloseParenthesisSymbol) {
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters); out = new ParsedParamListStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()),
parameters);
PROGRESS_TOKEN(currentToken); PROGRESS_TOKEN(currentToken);
return true; return true;
} }
@ -448,7 +456,9 @@ namespace MalachScript::Parser {
PROGRESS_TOKEN(currentToken); PROGRESS_TOKEN(currentToken);
} }
EXPECT_TOKEN(currentToken, CloseParenthesisSymbol); EXPECT_TOKEN(currentToken, CloseParenthesisSymbol);
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters); out = new ParsedParamListStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()),
parameters);
return true; return true;
} }
@ -471,7 +481,7 @@ namespace MalachScript::Parser {
} }
} }
bool Parser::ParseVirtProp([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, bool Parser::ParseVirtProp(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
const log_func& log) { const log_func& log) {
const auto* current = currentToken; const auto* current = currentToken;
AccessModifier access = AccessModifier::Public; AccessModifier access = AccessModifier::Public;
@ -526,7 +536,9 @@ namespace MalachScript::Parser {
} }
if (hasGet) { if (hasGet) {
logError(DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()), {}); logError(DiagnosticType::DoubleProperty,
ScriptTextSpan(start, current->GetSpan().GetEnd(), current->GetSpan().GetScriptName()),
{});
} }
hasGet = true; hasGet = true;
} else if (current->GetKind() == LexTokenKind::SetKeyword) { } else if (current->GetKind() == LexTokenKind::SetKeyword) {
@ -545,7 +557,9 @@ namespace MalachScript::Parser {
} }
if (hasSet) { if (hasSet) {
logError(DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()), {}); logError(DiagnosticType::DoubleProperty,
ScriptTextSpan(start, current->GetSpan().GetEnd(), current->GetSpan().GetScriptName()),
{});
} }
hasSet = true; hasSet = true;
} else { } else {
@ -558,10 +572,11 @@ namespace MalachScript::Parser {
PROGRESS_TOKEN(current); PROGRESS_TOKEN(current);
} }
out = new ParsedVirtPropStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedVirtPropStatement(
access, typeStatement.TakeOwnership(), ref, identifier, hasGet, getConst, ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
getAttr, getStatement.TakeOwnership(), hasSet, setConst, setAttr, current->GetSpan().GetScriptName()),
setStatement.TakeOwnership()); access, typeStatement.TakeOwnership(), ref, identifier, hasGet, getConst, getAttr,
getStatement.TakeOwnership(), hasSet, setConst, setAttr, setStatement.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
} }
@ -590,7 +605,8 @@ namespace MalachScript::Parser {
logUnexpectedTokenWithoutExpected(current); logUnexpectedTokenWithoutExpected(current);
} }
} }
out = new ParsedIfStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedIfStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
condition.TakeOwnership(), body.TakeOwnership(), elseStatement.TakeOwnership()); condition.TakeOwnership(), body.TakeOwnership(), elseStatement.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
@ -637,8 +653,9 @@ namespace MalachScript::Parser {
// TODO: Default values // TODO: Default values
// TODO: Creating multiple vars in a single line (int a, b, c) // TODO: Creating multiple vars in a single line (int a, b, c)
EXPECT_TOKEN(current, SemicolonSymbol); EXPECT_TOKEN(current, SemicolonSymbol);
out = new ParsedVarStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), access, out = new ParsedVarStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
typeStatement.TakeOwnership(), identifier); current->GetSpan().GetScriptName()),
access, typeStatement.TakeOwnership(), identifier);
currentToken = current; currentToken = current;
return true; return true;
} }
@ -668,8 +685,10 @@ namespace MalachScript::Parser {
logUnexpectedToken(CloseCurlyParenthesisSymbol, current); logUnexpectedToken(CloseCurlyParenthesisSymbol, current);
} }
out = new ParsedStatBlockStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out =
statements); new ParsedStatBlockStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
statements);
currentToken = current; currentToken = current;
return true; return true;
} }
@ -740,9 +759,10 @@ namespace MalachScript::Parser {
currentToken = current; currentToken = current;
return true; return true;
} }
out = new ParsedBinaryStatement<AssignmentOperator>( out = new ParsedBinaryStatement<AssignmentOperator>(ScriptTextSpan(currentToken->GetSpan().GetStart(),
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand.TakeOwnership(), op, current->GetSpan().GetEnd(),
rightHand.TakeOwnership()); current->GetSpan().GetScriptName()),
leftHand.TakeOwnership(), op, rightHand.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
} }
@ -764,8 +784,9 @@ namespace MalachScript::Parser {
currentToken = current; \ currentToken = current; \
return true; \ return true; \
} \ } \
out = new ParsedBinaryStatement < operator>(TextSpan(currentToken->GetSpan().GetStart(), \ out = new ParsedBinaryStatement < operator>(ScriptTextSpan(currentToken->GetSpan().GetStart(), \
current->GetSpan().GetEnd()), \ current->GetSpan().GetEnd(), \
current->GetSpan().GetScriptName()), \
leftHand.TakeOwnership(), name, rightHand.TakeOwnership()); \ leftHand.TakeOwnership(), name, rightHand.TakeOwnership()); \
currentToken = current; \ currentToken = current; \
return true; \ return true; \
@ -804,12 +825,16 @@ namespace MalachScript::Parser {
// TODO: remainder of // TODO: remainder of
if (current->GetKind() == LexTokenKind::PlusPlusSymbol) { if (current->GetKind() == LexTokenKind::PlusPlusSymbol) {
operand = new ParsedIncrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()), operand =
operand.TakeOwnership()); new ParsedIncrementStatement(ScriptTextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
operand.TakeOwnership());
PROGRESS_TOKEN(current); PROGRESS_TOKEN(current);
} else if (current->GetKind() == LexTokenKind::MinusMinusSymbol) { } else if (current->GetKind() == LexTokenKind::MinusMinusSymbol) {
operand = new ParsedDecrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()), operand =
operand.TakeOwnership()); new ParsedDecrementStatement(ScriptTextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
operand.TakeOwnership());
PROGRESS_TOKEN(current); PROGRESS_TOKEN(current);
} }
@ -897,7 +922,9 @@ namespace MalachScript::Parser {
ScopedPtr<const ParsedStatement> returnBody; ScopedPtr<const ParsedStatement> returnBody;
ParseAssign(returnBody, currentToken, log); ParseAssign(returnBody, currentToken, log);
EXPECT_TOKEN(currentToken, SemicolonSymbol); EXPECT_TOKEN(currentToken, SemicolonSymbol);
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody.TakeOwnership()); out = new ParsedReturnStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()),
returnBody.TakeOwnership());
return true; return true;
} }
bool Parser::ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, bool Parser::ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
@ -913,7 +940,9 @@ namespace MalachScript::Parser {
std::vector<Identifier> scope; std::vector<Identifier> scope;
auto start = currentToken->GetSpan().GetStart(); auto start = currentToken->GetSpan().GetStart();
if (ParseScope(scope, currentToken, log)) { if (ParseScope(scope, currentToken, log)) {
out = new ParsedVarAccessStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), scope); out = new ParsedVarAccessStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()),
scope);
return true; return true;
} }
Identifier identifier; Identifier identifier;
@ -934,7 +963,8 @@ namespace MalachScript::Parser {
auto start = currentToken->GetSpan().GetStart(); auto start = currentToken->GetSpan().GetStart();
PROGRESS_TOKEN(currentToken); PROGRESS_TOKEN(currentToken);
EXPECT_TOKEN(currentToken, SemicolonSymbol); EXPECT_TOKEN(currentToken, SemicolonSymbol);
out = new ParsedContinueStatement(TextSpan(start, currentToken->GetSpan().GetEnd())); out = new ParsedContinueStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()));
return true; return true;
} }
bool Parser::ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, bool Parser::ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
@ -945,7 +975,8 @@ namespace MalachScript::Parser {
auto start = currentToken->GetSpan().GetStart(); auto start = currentToken->GetSpan().GetStart();
PROGRESS_TOKEN(currentToken); PROGRESS_TOKEN(currentToken);
EXPECT_TOKEN(currentToken, SemicolonSymbol); EXPECT_TOKEN(currentToken, SemicolonSymbol);
out = new ParsedBreakStatement(TextSpan(start, currentToken->GetSpan().GetEnd())); out = new ParsedBreakStatement(
ScriptTextSpan(start, currentToken->GetSpan().GetEnd(), currentToken->GetSpan().GetScriptName()));
return true; return true;
} }
bool Parser::ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, bool Parser::ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
@ -983,7 +1014,8 @@ namespace MalachScript::Parser {
return false; return false;
} }
out = new ParsedForStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedForStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
init.TakeOwnership(), condition.TakeOwnership(), increment, init.TakeOwnership(), condition.TakeOwnership(), increment,
statementBlock.TakeOwnership()); statementBlock.TakeOwnership());
currentToken = current; currentToken = current;
@ -1009,7 +1041,8 @@ namespace MalachScript::Parser {
logUnexpectedTokenWithoutExpected(current); logUnexpectedTokenWithoutExpected(current);
return false; return false;
} }
out = new ParsedWhileStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedWhileStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
condition.TakeOwnership(), body.TakeOwnership()); condition.TakeOwnership(), body.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
@ -1035,7 +1068,8 @@ namespace MalachScript::Parser {
} }
EXPECT_TOKEN(current, CloseParenthesisSymbol); EXPECT_TOKEN(current, CloseParenthesisSymbol);
EXPECT_TOKEN(current, SemicolonSymbol); EXPECT_TOKEN(current, SemicolonSymbol);
out = new ParsedDoWhileStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedDoWhileStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
condition.TakeOwnership(), body.TakeOwnership()); condition.TakeOwnership(), body.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
@ -1060,7 +1094,8 @@ namespace MalachScript::Parser {
return false; return false;
} }
out = new ParsedTryStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedTryStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
tryStatement.TakeOwnership(), catchStatement.TakeOwnership()); tryStatement.TakeOwnership(), catchStatement.TakeOwnership());
currentToken = current; currentToken = current;
return true; return true;
@ -1103,7 +1138,8 @@ namespace MalachScript::Parser {
// Consume } // Consume }
PROGRESS_TOKEN(current); PROGRESS_TOKEN(current);
out = new ParsedSwitchStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedSwitchStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
expression.TakeOwnership(), caseStatements); expression.TakeOwnership(), caseStatements);
currentToken = current; currentToken = current;
return true; return true;
@ -1146,7 +1182,8 @@ namespace MalachScript::Parser {
} }
} }
out = new ParsedCaseStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), out = new ParsedCaseStatement(ScriptTextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd(),
current->GetSpan().GetScriptName()),
expression.TakeOwnership(), statements); expression.TakeOwnership(), statements);
currentToken = current; currentToken = current;
return true; return true;

View File

@ -11,12 +11,11 @@
namespace MalachScript::Parser { namespace MalachScript::Parser {
class Parser { class Parser {
public: public:
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::string_view scriptName, static const ParsedScriptStatement* Parse(const LexToken* firstToken, Diagnostics::Logger* diagnostics);
Diagnostics::Logger* diagnostics);
private: private:
using log_func = const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType, using log_func = const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType,
const TextSpan&, const std::vector<std::string>&)>; const ScriptTextSpan&, const std::vector<std::string>&)>;
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////
// Underlying functions are laid out in the order they are defined in the grammar.ebnf // // Underlying functions are laid out in the order they are defined in the grammar.ebnf //

View File

@ -15,18 +15,18 @@
#include "ParsedStatementKind.hpp" #include "ParsedStatementKind.hpp"
namespace MalachScript::Parser { namespace MalachScript::Parser {
class ParsedStatement { class ParsedStatement {
TextSpan _span; ScriptTextSpan _span;
public: public:
ParsedStatement(TextSpan span) : _span(span) {} ParsedStatement(ScriptTextSpan span) : _span(span) {}
virtual ~ParsedStatement() = default; virtual ~ParsedStatement() = default;
[[nodiscard]] virtual ParsedStatementKind GetKind() const noexcept = 0; [[nodiscard]] virtual ParsedStatementKind GetKind() const noexcept = 0;
[[nodiscard]] inline const TextSpan& GetSpan() const noexcept { return _span; } [[nodiscard]] inline const ScriptTextSpan& GetSpan() const noexcept { return _span; }
}; };
template <ParsedStatementKind kind> class ParsedStatementImpl : public ParsedStatement { template <ParsedStatementKind kind> class ParsedStatementImpl : public ParsedStatement {
public: public:
ParsedStatementImpl(TextSpan span) : ParsedStatement(span) {} ParsedStatementImpl(ScriptTextSpan span) : ParsedStatement(span) {}
[[nodiscard]] inline ParsedStatementKind GetKind() const noexcept final { return kind; } [[nodiscard]] inline ParsedStatementKind GetKind() const noexcept final { return kind; }
}; };
@ -34,7 +34,7 @@ namespace MalachScript::Parser {
std::vector<std::unique_ptr<const ParsedStatement>> _statements; std::vector<std::unique_ptr<const ParsedStatement>> _statements;
public: public:
ParsedScriptStatement(TextSpan span, const std::vector<const ParsedStatement*>& statements) ParsedScriptStatement(ScriptTextSpan span, const std::vector<const ParsedStatement*>& statements)
: ParsedStatementImpl<ParsedStatementKind::Script>(span), _statements(statements.size()) { : ParsedStatementImpl<ParsedStatementKind::Script>(span), _statements(statements.size()) {
for (size_t i = 0; i < statements.size(); i++) for (size_t i = 0; i < statements.size(); i++)
_statements[i] = std::unique_ptr<const ParsedStatement>(statements[i]); _statements[i] = std::unique_ptr<const ParsedStatement>(statements[i]);
@ -47,7 +47,7 @@ namespace MalachScript::Parser {
class ParsedClassStatement : public ParsedStatementImpl<ParsedStatementKind::Class> { class ParsedClassStatement : public ParsedStatementImpl<ParsedStatementKind::Class> {
public: public:
ParsedClassStatement(TextSpan span, ClassAttr classAttr, Identifier identifier, ParsedClassStatement(ScriptTextSpan span, ClassAttr classAttr, Identifier identifier,
const 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), : ParsedStatementImpl<ParsedStatementKind::Class>(span), _classAttr(classAttr), _identifier(identifier),
_inherits(inherits), _body(body.size()) { _inherits(inherits), _body(body.size()) {
@ -75,7 +75,7 @@ namespace MalachScript::Parser {
Identifier _defineTo; Identifier _defineTo;
public: public:
ParsedTypeDefStatement(TextSpan span, const Identifier& defineFrom, const Identifier& defineTo) ParsedTypeDefStatement(ScriptTextSpan span, const Identifier& defineFrom, const Identifier& defineTo)
: ParsedStatementImpl<ParsedStatementKind::TypeDef>(span), _defineFrom(defineFrom), _defineTo(defineTo) {} : ParsedStatementImpl<ParsedStatementKind::TypeDef>(span), _defineFrom(defineFrom), _defineTo(defineTo) {}
[[nodiscard]] inline const Identifier& GetDefineFrom() const noexcept { return _defineFrom; } [[nodiscard]] inline const Identifier& GetDefineFrom() const noexcept { return _defineFrom; }
@ -87,7 +87,7 @@ namespace MalachScript::Parser {
std::unique_ptr<const ParsedStatement> _parsedScript; std::unique_ptr<const ParsedStatement> _parsedScript;
public: public:
ParsedNamespaceStatement(TextSpan span, const Identifier& identifier, const ParsedScriptStatement* script) ParsedNamespaceStatement(ScriptTextSpan span, const Identifier& identifier, const ParsedScriptStatement* script)
: ParsedStatementImpl<ParsedStatementKind::Namespace>(span), _identifier(identifier), : ParsedStatementImpl<ParsedStatementKind::Namespace>(span), _identifier(identifier),
_parsedScript(script) {} _parsedScript(script) {}
@ -104,7 +104,7 @@ namespace MalachScript::Parser {
ScopedIdentifier _scopedIdentifier; ScopedIdentifier _scopedIdentifier;
public: public:
ParsedTypeStatement(TextSpan span, bool isConst, bool isArray, bool isHandle, ParsedTypeStatement(ScriptTextSpan span, bool isConst, bool isArray, bool isHandle,
const ScopedIdentifier& scopedIdentifier) const ScopedIdentifier& scopedIdentifier)
: ParsedStatementImpl<ParsedStatementKind::Type>(span), _isConst(isConst), _isArray(isArray), : ParsedStatementImpl<ParsedStatementKind::Type>(span), _isConst(isConst), _isArray(isArray),
_isHandle(isHandle), _scopedIdentifier(scopedIdentifier) {} _isHandle(isHandle), _scopedIdentifier(scopedIdentifier) {}
@ -155,7 +155,7 @@ namespace MalachScript::Parser {
std::vector<std::unique_ptr<const ParsedParameter>> _parameters; std::vector<std::unique_ptr<const ParsedParameter>> _parameters;
public: public:
ParsedParamListStatement(TextSpan span, const std::vector<const ParsedParameter*>& parameters) ParsedParamListStatement(ScriptTextSpan span, const std::vector<const ParsedParameter*>& parameters)
: ParsedStatementImpl<ParsedStatementKind::ParamList>(span), _parameters(parameters.size()) { : ParsedStatementImpl<ParsedStatementKind::ParamList>(span), _parameters(parameters.size()) {
for (size_t i = 0; i < parameters.size(); i++) { for (size_t i = 0; i < parameters.size(); i++) {
_parameters[i] = std::unique_ptr<const ParsedParameter>(parameters[i]); _parameters[i] = std::unique_ptr<const ParsedParameter>(parameters[i]);
@ -181,7 +181,7 @@ namespace MalachScript::Parser {
std::unique_ptr<const ParsedStatement> _statBlock; std::unique_ptr<const ParsedStatement> _statBlock;
public: public:
ParsedFuncStatement(const TextSpan& span, bool isShared, bool isExternal, AccessModifier access, ParsedFuncStatement(const ScriptTextSpan& span, bool isShared, bool isExternal, AccessModifier access,
const ParsedStatement* type, bool returnsReference, const Identifier& identifier, const ParsedStatement* type, bool returnsReference, const Identifier& identifier,
const ParsedStatement* paramList, bool isConst, FuncAttr funcAttr, const ParsedStatement* paramList, bool isConst, FuncAttr funcAttr,
const ParsedStatement* statBlock) const ParsedStatement* statBlock)
@ -209,7 +209,7 @@ namespace MalachScript::Parser {
class ParsedVirtPropStatement : public ParsedStatementImpl<ParsedStatementKind::VirtProp> { class ParsedVirtPropStatement : public ParsedStatementImpl<ParsedStatementKind::VirtProp> {
public: public:
ParsedVirtPropStatement(const TextSpan& span, AccessModifier access, const ParsedStatement* returnType, ParsedVirtPropStatement(const ScriptTextSpan& span, AccessModifier access, const ParsedStatement* returnType,
bool isReturnTypeRef, Identifier identifier, bool hasGet, bool getConst, bool isReturnTypeRef, Identifier identifier, bool hasGet, bool getConst,
FuncAttr getAttr, const ParsedStatement* getStatement, bool hasSet, bool setConst, FuncAttr getAttr, const ParsedStatement* getStatement, bool hasSet, bool setConst,
FuncAttr setAttr, const ParsedStatement* setStatement) FuncAttr setAttr, const ParsedStatement* setStatement)
@ -257,7 +257,7 @@ namespace MalachScript::Parser {
class ParsedStatBlockStatement : public ParsedStatementImpl<ParsedStatementKind::StatBlock> { class ParsedStatBlockStatement : public ParsedStatementImpl<ParsedStatementKind::StatBlock> {
public: public:
ParsedStatBlockStatement(const TextSpan& span, const std::vector<const ParsedStatement*>& statements) ParsedStatBlockStatement(const ScriptTextSpan& span, const std::vector<const ParsedStatement*>& statements)
: ParsedStatementImpl(span), _statements(statements.size()) { : ParsedStatementImpl(span), _statements(statements.size()) {
for (size_t i = 0; i < statements.size(); i++) { for (size_t i = 0; i < statements.size(); i++) {
_statements[i] = std::unique_ptr<const ParsedStatement>(statements[i]); _statements[i] = std::unique_ptr<const ParsedStatement>(statements[i]);
@ -274,7 +274,7 @@ namespace MalachScript::Parser {
class ParsedVarStatement : public ParsedStatementImpl<ParsedStatementKind::Var> { class ParsedVarStatement : public ParsedStatementImpl<ParsedStatementKind::Var> {
public: public:
ParsedVarStatement(const TextSpan& span, AccessModifier access, const ParsedTypeStatement* typeStatement, ParsedVarStatement(const ScriptTextSpan& span, AccessModifier access, const ParsedTypeStatement* typeStatement,
Identifier identifier) Identifier identifier)
: ParsedStatementImpl(span), _access(access), _typeStatement(typeStatement), _identifier(identifier) {} : ParsedStatementImpl(span), _access(access), _typeStatement(typeStatement), _identifier(identifier) {}
@ -292,7 +292,7 @@ namespace MalachScript::Parser {
class ParsedIfStatement : public ParsedStatementImpl<ParsedStatementKind::If> { class ParsedIfStatement : public ParsedStatementImpl<ParsedStatementKind::If> {
public: public:
ParsedIfStatement(const TextSpan& span, const ParsedStatement* condition, const ParsedStatement* body, ParsedIfStatement(const ScriptTextSpan& span, const ParsedStatement* condition, const ParsedStatement* body,
const ParsedStatement* elseStatement) const ParsedStatement* elseStatement)
: ParsedStatementImpl(span), _condition(condition), _body(body), _elseStatement(elseStatement) {} : ParsedStatementImpl(span), _condition(condition), _body(body), _elseStatement(elseStatement) {}
@ -313,7 +313,7 @@ namespace MalachScript::Parser {
template <class TOperator> template <class TOperator>
class ParsedBinaryStatement : public ParsedStatementImpl<ParsedStatementKind::BinaryExpression> { class ParsedBinaryStatement : public ParsedStatementImpl<ParsedStatementKind::BinaryExpression> {
public: public:
ParsedBinaryStatement(const TextSpan& span, const ParsedStatement* leftHand, TOperator op, ParsedBinaryStatement(const ScriptTextSpan& span, const ParsedStatement* leftHand, TOperator op,
const ParsedStatement* rightHand) const ParsedStatement* rightHand)
: ParsedStatementImpl(span), _leftHand(leftHand), _operator(op), _rightHand(rightHand) {} : ParsedStatementImpl(span), _leftHand(leftHand), _operator(op), _rightHand(rightHand) {}
@ -327,12 +327,12 @@ namespace MalachScript::Parser {
class ParsedVoidStatement : public ParsedStatementImpl<ParsedStatementKind::Void> { class ParsedVoidStatement : public ParsedStatementImpl<ParsedStatementKind::Void> {
public: public:
ParsedVoidStatement(const TextSpan& span) : ParsedStatementImpl(span) {} ParsedVoidStatement(const ScriptTextSpan& span) : ParsedStatementImpl(span) {}
}; };
template <class T> class ParsedLiteralStatement : public ParsedStatementImpl<ParsedStatementKind::Literal> { template <class T> class ParsedLiteralStatement : public ParsedStatementImpl<ParsedStatementKind::Literal> {
public: public:
ParsedLiteralStatement(const TextSpan& span, T literalValue) ParsedLiteralStatement(const ScriptTextSpan& span, T literalValue)
: ParsedStatementImpl(span), _literalValue(literalValue) {} : ParsedStatementImpl(span), _literalValue(literalValue) {}
[[nodiscard]] inline const T& GetLiteralValue() const noexcept { return _literalValue; } [[nodiscard]] inline const T& GetLiteralValue() const noexcept { return _literalValue; }
@ -343,7 +343,7 @@ namespace MalachScript::Parser {
class ParsedReturnStatement : public ParsedStatementImpl<ParsedStatementKind::Return> { class ParsedReturnStatement : public ParsedStatementImpl<ParsedStatementKind::Return> {
public: public:
ParsedReturnStatement(const TextSpan& span, const ParsedStatement* statement) ParsedReturnStatement(const ScriptTextSpan& span, const ParsedStatement* statement)
: ParsedStatementImpl(span), _statement(statement) {} : ParsedStatementImpl(span), _statement(statement) {}
private: private:
@ -352,7 +352,7 @@ namespace MalachScript::Parser {
class ParsedVarAccessStatement : public ParsedStatementImpl<ParsedStatementKind::VarAccess> { class ParsedVarAccessStatement : public ParsedStatementImpl<ParsedStatementKind::VarAccess> {
public: public:
ParsedVarAccessStatement(const TextSpan& span, std::vector<Identifier> scope) ParsedVarAccessStatement(const ScriptTextSpan& span, std::vector<Identifier> scope)
: ParsedStatementImpl(span), _scope(std::move(scope)) {} : ParsedStatementImpl(span), _scope(std::move(scope)) {}
private: private:
@ -361,7 +361,7 @@ namespace MalachScript::Parser {
class ParsedIncrementStatement : public ParsedStatementImpl<ParsedStatementKind::Increment> { class ParsedIncrementStatement : public ParsedStatementImpl<ParsedStatementKind::Increment> {
public: public:
ParsedIncrementStatement(const TextSpan& span, const ParsedStatement* statement) ParsedIncrementStatement(const ScriptTextSpan& span, const ParsedStatement* statement)
: ParsedStatementImpl(span), _statement(statement) {} : ParsedStatementImpl(span), _statement(statement) {}
private: private:
@ -370,7 +370,7 @@ namespace MalachScript::Parser {
class ParsedDecrementStatement : public ParsedStatementImpl<ParsedStatementKind::Decrement> { class ParsedDecrementStatement : public ParsedStatementImpl<ParsedStatementKind::Decrement> {
public: public:
ParsedDecrementStatement(const TextSpan& span, const ParsedStatement* statement) ParsedDecrementStatement(const ScriptTextSpan& span, const ParsedStatement* statement)
: ParsedStatementImpl(span), _statement(statement) {} : ParsedStatementImpl(span), _statement(statement) {}
private: private:
@ -379,17 +379,17 @@ namespace MalachScript::Parser {
class ParsedContinueStatement : public ParsedStatementImpl<ParsedStatementKind::Continue> { class ParsedContinueStatement : public ParsedStatementImpl<ParsedStatementKind::Continue> {
public: public:
ParsedContinueStatement(const TextSpan& span) : ParsedStatementImpl(span) {} ParsedContinueStatement(const ScriptTextSpan& span) : ParsedStatementImpl(span) {}
}; };
class ParsedBreakStatement : public ParsedStatementImpl<ParsedStatementKind::Break> { class ParsedBreakStatement : public ParsedStatementImpl<ParsedStatementKind::Break> {
public: public:
ParsedBreakStatement(const TextSpan& span) : ParsedStatementImpl(span) {} ParsedBreakStatement(const ScriptTextSpan& span) : ParsedStatementImpl(span) {}
}; };
class ParsedForStatement : public ParsedStatementImpl<ParsedStatementKind::For> { class ParsedForStatement : public ParsedStatementImpl<ParsedStatementKind::For> {
public: public:
ParsedForStatement(const TextSpan& span, const ParsedStatement* init, const ParsedStatement* condition, ParsedForStatement(const ScriptTextSpan& span, const ParsedStatement* init, const ParsedStatement* condition,
std::vector<const ParsedStatement*> increment, const ParsedStatement* body) std::vector<const ParsedStatement*> increment, const ParsedStatement* body)
: ParsedStatementImpl(span), _init(init), _condition(condition), _increment(increment.size()), _body(body) { : ParsedStatementImpl(span), _init(init), _condition(condition), _increment(increment.size()), _body(body) {
for (size_t i = 0; i < increment.size(); i++) { for (size_t i = 0; i < increment.size(); i++) {
@ -413,7 +413,7 @@ namespace MalachScript::Parser {
class ParsedWhileStatement : public ParsedStatementImpl<ParsedStatementKind::While> { class ParsedWhileStatement : public ParsedStatementImpl<ParsedStatementKind::While> {
public: public:
ParsedWhileStatement(const TextSpan& span, const ParsedStatement* condition, const ParsedStatement* body) ParsedWhileStatement(const ScriptTextSpan& span, const ParsedStatement* condition, const ParsedStatement* body)
: ParsedStatementImpl(span), _condition(condition), _body(body) {} : ParsedStatementImpl(span), _condition(condition), _body(body) {}
private: private:
@ -423,7 +423,8 @@ namespace MalachScript::Parser {
class ParsedDoWhileStatement : public ParsedStatementImpl<ParsedStatementKind::DoWhile> { class ParsedDoWhileStatement : public ParsedStatementImpl<ParsedStatementKind::DoWhile> {
public: public:
ParsedDoWhileStatement(const TextSpan& span, const ParsedStatement* condition, const ParsedStatement* body) ParsedDoWhileStatement(const ScriptTextSpan& span, const ParsedStatement* condition,
const ParsedStatement* body)
: ParsedStatementImpl(span), _condition(condition), _body(body) {} : ParsedStatementImpl(span), _condition(condition), _body(body) {}
private: private:
@ -433,7 +434,7 @@ namespace MalachScript::Parser {
class ParsedTryStatement : public ParsedStatementImpl<ParsedStatementKind::Try> { class ParsedTryStatement : public ParsedStatementImpl<ParsedStatementKind::Try> {
public: public:
ParsedTryStatement(const TextSpan& span, const ParsedStatement* tryStatement, ParsedTryStatement(const ScriptTextSpan& span, const ParsedStatement* tryStatement,
const ParsedStatement* catchStatement) const ParsedStatement* catchStatement)
: ParsedStatementImpl(span), _tryStatement(tryStatement), _catchStatement(catchStatement) {} : ParsedStatementImpl(span), _tryStatement(tryStatement), _catchStatement(catchStatement) {}
@ -444,7 +445,7 @@ namespace MalachScript::Parser {
class ParsedSwitchStatement : public ParsedStatementImpl<ParsedStatementKind::Switch> { class ParsedSwitchStatement : public ParsedStatementImpl<ParsedStatementKind::Switch> {
public: public:
ParsedSwitchStatement(const TextSpan& span, const ParsedStatement* expression, ParsedSwitchStatement(const ScriptTextSpan& span, const ParsedStatement* expression,
const std::vector<const ParsedStatement*>& cases) const std::vector<const ParsedStatement*>& cases)
: ParsedStatementImpl(span), _expression(expression), _cases(cases.size()) { : ParsedStatementImpl(span), _expression(expression), _cases(cases.size()) {
for (size_t i = 0; i < cases.size(); i++) { for (size_t i = 0; i < cases.size(); i++) {
@ -459,7 +460,7 @@ namespace MalachScript::Parser {
class ParsedCaseStatement : public ParsedStatementImpl<ParsedStatementKind::Case> { class ParsedCaseStatement : public ParsedStatementImpl<ParsedStatementKind::Case> {
public: public:
ParsedCaseStatement(const TextSpan& span, const ParsedStatement* expression, ParsedCaseStatement(const ScriptTextSpan& span, const ParsedStatement* expression,
const std::vector<const ParsedStatement*>& statements) const std::vector<const ParsedStatement*>& statements)
: ParsedStatementImpl(span), _expression(expression), _statements(statements.size()) { : ParsedStatementImpl(span), _expression(expression), _statements(statements.size()) {
for (size_t i = 0; i < statements.size(); i++) { for (size_t i = 0; i < statements.size(); i++) {

View File

@ -2,6 +2,8 @@
#define MALACHSCRIPT_TEXTSPAN_HPP #define MALACHSCRIPT_TEXTSPAN_HPP
#include <cstddef> #include <cstddef>
#include <string>
namespace MalachScript { namespace MalachScript {
class TextSpan { class TextSpan {
size_t _start; size_t _start;
@ -14,6 +16,24 @@ namespace MalachScript {
inline bool operator==(const TextSpan& rhs) const { return _start == rhs._start && _end == rhs._end; } inline bool operator==(const TextSpan& rhs) const { return _start == rhs._start && _end == rhs._end; }
inline bool operator!=(const TextSpan& rhs) const { return !(rhs == *this); } inline bool operator!=(const TextSpan& rhs) const { return !(rhs == *this); }
}; };
class ScriptTextSpan {
TextSpan _span;
const std::string_view& _scriptName;
public:
inline ScriptTextSpan(size_t start, size_t end, const std::string_view& scriptName)
: _span(start, end), _scriptName(scriptName) {}
[[nodiscard]] inline TextSpan GetSpan() const noexcept { return _span; }
[[nodiscard]] inline const std::string_view& GetScriptName() const noexcept { return _scriptName; }
inline bool operator==(const ScriptTextSpan& rhs) const {
return _span == rhs._span && _scriptName == rhs._scriptName;
}
inline bool operator!=(const ScriptTextSpan& rhs) const { return !(rhs == *this); }
[[nodiscard]] inline size_t GetStart() const noexcept { return _span.GetStart(); }
[[nodiscard]] inline size_t GetEnd() const noexcept { return _span.GetEnd(); }
};
} }
#endif // MALACHSCRIPT_TEXTSPAN_HPP #endif // MALACHSCRIPT_TEXTSPAN_HPP