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 lexer = MalachScript::Parser::Lexer("diag", script, &logger);
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();
const MalachScript::Binder::Binder::log_func log =
[&logger](MalachScript::Diagnostics::DiagnosticLevel level, MalachScript::Diagnostics::DiagnosticType type,
const MalachScript::TextSpan& span,
const std::vector<std::string>& formats) { logger.Log(level, type, "", span, formats); };
const MalachScript::ScriptTextSpan& span,
const std::vector<std::string>& formats) { logger.Log(level, type, span, formats); };
MalachScript::Binder::Binder::Bind(ns, {parsedResult}, log);
const MalachScript::Diagnostics::Diagnostic* diag = nullptr;

View File

@ -66,7 +66,7 @@ namespace MalachScript::Binder {
break;
}
type = new BoundType(identifier, s->GetClassAttr());
type = new BoundType(identifier, s->GetClassAttr(), s->GetSpan());
if (activeType.has_value()) {
activeType.value()->RegisterType(identifier, type.value());
} 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) {
std::vector<const BoundType*> s = {};
for (const auto& t : ns->GetTypes()) {
t.second->Finalise();
FinaliseType(t.second, s, log);
}
for (const auto& n : ns->GetNamespaces()) {
FinaliseNamespace(n.second, log);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,6 +28,9 @@ namespace MalachScript::Diagnostics {
return util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
case DiagnosticType::TypeAlreadyDefined:
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());
}

View File

@ -9,25 +9,29 @@ namespace MalachScript::Diagnostics {
std::vector<Diagnostic> _messages;
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 = {}) {
_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) {
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,
inline void LogTrace(DiagnosticType type, const ScriptTextSpan& span,
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) {
Log(DiagnosticLevel::Critical, type, scriptName, span);
inline void LogInfo(DiagnosticType type, const ScriptTextSpan& 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; }

View File

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

View File

@ -25,7 +25,8 @@ namespace MalachScript::Parser {
auto start = _position;
auto c = Consume();
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 '*': {
auto n = Peek();
if (n == '*') {
@ -34,71 +35,81 @@ namespace MalachScript::Parser {
if (n == '=') {
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 == '=') {
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 '/':
if (Peek() == '=') {
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 '%':
if (Peek() == '=') {
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 '+': {
auto n = Peek();
if (n == '=') {
Progress();
// +=
return Create<LexTokenImpl<LexTokenKind::PlusEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::PlusEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '+') {
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 '-': {
auto n = Peek();
if (n == '=') {
Progress();
// -=
return Create<LexTokenImpl<LexTokenKind::MinusEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::MinusEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '-') {
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 '<': {
auto n = Peek();
if (n == '=') {
Progress();
// <=
return Create<LexTokenImpl<LexTokenKind::LessThanEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::LessThanEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '<') {
Progress();
@ -106,20 +117,23 @@ namespace MalachScript::Parser {
Progress();
// <<=
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 '>': {
auto n = Peek();
if (n == '=') {
Progress();
// >=
return Create<LexTokenImpl<LexTokenKind::GreaterThanEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::GreaterThanEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '>') {
Progress();
@ -128,7 +142,7 @@ namespace MalachScript::Parser {
Progress();
// >>=
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanEqualsSymbol>>(
TextSpan(start, start + 3));
ScriptTextSpan(start, start + 3, _scriptName));
}
if (n == '>') {
Progress();
@ -136,125 +150,159 @@ namespace MalachScript::Parser {
Progress();
// >>>=
return Create<LexTokenImpl<LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol>>(
TextSpan(start, start + 4));
ScriptTextSpan(start, start + 4, _scriptName));
}
// >>>
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 ')': return Create<LexTokenImpl<LexTokenKind::CloseParenthesisSymbol>>(TextSpan(start, start + 1));
case '(':
return Create<LexTokenImpl<LexTokenKind::OpenParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case ')':
return Create<LexTokenImpl<LexTokenKind::CloseParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '=': {
if (Peek() == '=') {
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 '!': {
auto n = Peek();
if (n == '=') {
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') {
Progress(2);
// !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 ':': {
if (Peek() == ':') {
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 '&': {
auto n = Peek();
if (n == '=') {
Progress();
// &=
return Create<LexTokenImpl<LexTokenKind::AmpersandEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::AmpersandEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '&') {
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 '{': return Create<LexTokenImpl<LexTokenKind::OpenCurlyParenthesisSymbol>>(TextSpan(start, start + 1));
case ',':
return Create<LexTokenImpl<LexTokenKind::CommaSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '{':
return Create<LexTokenImpl<LexTokenKind::OpenCurlyParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '}':
return Create<LexTokenImpl<LexTokenKind::CloseCurlyParenthesisSymbol>>(TextSpan(start, start + 1));
case ';': return Create<LexTokenImpl<LexTokenKind::SemicolonSymbol>>(TextSpan(start, start + 1));
return Create<LexTokenImpl<LexTokenKind::CloseCurlyParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case ';':
return Create<LexTokenImpl<LexTokenKind::SemicolonSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '|': {
auto n = Peek();
if (n == '=') {
Progress();
// |=
return Create<LexTokenImpl<LexTokenKind::VerticalLineEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::VerticalLineEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '|') {
Progress();
// ||
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 '^': {
auto n = Peek();
if (n == '=') {
Progress();
// ^=
return Create<LexTokenImpl<LexTokenKind::CaretEqualsSymbol>>(TextSpan(start, start + 2));
return Create<LexTokenImpl<LexTokenKind::CaretEqualsSymbol>>(
ScriptTextSpan(start, start + 2, _scriptName));
}
if (n == '^') {
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 '.': return Create<LexTokenImpl<LexTokenKind::DotSymbol>>(TextSpan(start, start + 1));
case '[': return Create<LexTokenImpl<LexTokenKind::OpenBlockParenthesisSymbol>>(TextSpan(start, start + 1));
case '~':
return Create<LexTokenImpl<LexTokenKind::TildeSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '.':
return Create<LexTokenImpl<LexTokenKind::DotSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case '[':
return Create<LexTokenImpl<LexTokenKind::OpenBlockParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case ']':
return Create<LexTokenImpl<LexTokenKind::CloseBlockParenthesisSymbol>>(TextSpan(start, start + 1));
case '@': return Create<LexTokenImpl<LexTokenKind::AtSymbol>>(TextSpan(start, start + 1));
return Create<LexTokenImpl<LexTokenKind::CloseBlockParenthesisSymbol>>(
ScriptTextSpan(start, start + 1, _scriptName));
case '@':
return Create<LexTokenImpl<LexTokenKind::AtSymbol>>(ScriptTextSpan(start, start + 1, _scriptName));
case ' ':
case '\r':
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
case '\xEF': {
if (Peek() == '\xBB' && Peek(2) == '\xBF') {
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)});
return Create<LexTokenImpl<LexTokenKind::Unknown>>(TextSpan(start, start + 1));
return Create<LexTokenImpl<LexTokenKind::Unknown>>(ScriptTextSpan(start, start + 1, _scriptName));
}
case '0':
case '1':
@ -277,9 +325,9 @@ namespace MalachScript::Parser {
default:
if (IsAlphaNumericalOrUnderscore(c))
return LexKeywordOrIdentifier();
LogError(Diagnostics::DiagnosticType::UnknownCharacter, TextSpan(start, start + 1),
LogError(Diagnostics::DiagnosticType::UnknownCharacter, ScriptTextSpan(start, start + 1, _scriptName),
{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();
numericalSystem = 2;
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) {
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() {
@ -407,7 +455,7 @@ namespace MalachScript::Parser {
value <<= 4;
value += v;
}
return Create<IntegerLiteral>(TextSpan(start - 1, _position), value);
return Create<IntegerLiteral>(ScriptTextSpan(start - 1, _position, _scriptName), value);
}
IntegerLiteral* Lexer::LexOctal() {
auto start = _position;
@ -421,7 +469,7 @@ namespace MalachScript::Parser {
value <<= 3;
value += v;
}
return Create<IntegerLiteral>(TextSpan(start - 1, _position), value);
return Create<IntegerLiteral>(ScriptTextSpan(start - 1, _position, _scriptName), value);
}
IntegerLiteral* Lexer::LexBinary() {
auto start = _position;
@ -435,7 +483,7 @@ namespace MalachScript::Parser {
value <<= 1;
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) {
auto openingPos = _position;
@ -455,13 +503,13 @@ namespace MalachScript::Parser {
break;
}
if (current == '\0') {
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString, TextSpan(start, start + offset),
{"EndOfFile"});
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString,
ScriptTextSpan(start, start + offset, _scriptName), {"EndOfFile"});
break;
}
if (!heredoc && (current == '\n' || current == '\r')) {
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString, TextSpan(start, start + offset),
{"Newline"});
LogError(Diagnostics::DiagnosticType::ExpectedEndOfString,
ScriptTextSpan(start, start + offset, _scriptName), {"Newline"});
break;
}
offset++;
@ -470,7 +518,7 @@ namespace MalachScript::Parser {
if (heredoc) {
Progress(2);
}
return Create<StringLiteral>(TextSpan(openingPos, openingPos + _position),
return Create<StringLiteral>(ScriptTextSpan(openingPos, openingPos + _position, _scriptName),
ParseString(_script.substr(start, offset)));
}
@ -485,135 +533,151 @@ namespace MalachScript::Parser {
auto hash = Identifier::Hash(str);
switch (hash) {
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"):
return Create<LexTokenImpl<LexTokenKind::AbstractKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::AbstractKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::BoolKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::BoolKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::CaseKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::CaseKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::CatchKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::CatchKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::ConstKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::ConstKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::DefaultKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::DefaultKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::DoubleKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::DoubleKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::EnumKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::EnumKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::ExternalKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::ExternalKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::FinalKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::FinalKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::ForKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::ForKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::FuncdefKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::FuncdefKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::GetKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::GetKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::ImportKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::ImportKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::InoutKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::InoutKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::InterfaceKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::InterfaceKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::Int16Keyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::Int16Keyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::Int64Keyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::Int64Keyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::MixinKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::MixinKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::NotKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::NotKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::OrKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::OrKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::OverrideKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::OverrideKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::PropertyKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::PropertyKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::ReturnKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::ReturnKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::SharedKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::SharedKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::SwitchKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::SwitchKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::TrueKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::TrueKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::TypedefKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::TypedefKeyword>>(
ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::Uint8Keyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::Uint8Keyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::Uint32Keyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::Uint32Keyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
return Create<LexTokenImpl<LexTokenKind::VoidKeyword>>(TextSpan(start, _position));
return Create<LexTokenImpl<LexTokenKind::VoidKeyword>>(ScriptTextSpan(start, _position, _scriptName));
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"):
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) {

View File

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

View File

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

View File

@ -11,12 +11,11 @@
namespace MalachScript::Parser {
class Parser {
public:
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::string_view scriptName,
Diagnostics::Logger* diagnostics);
static const ParsedScriptStatement* Parse(const LexToken* firstToken, Diagnostics::Logger* diagnostics);
private:
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 //

View File

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

View File

@ -2,6 +2,8 @@
#define MALACHSCRIPT_TEXTSPAN_HPP
#include <cstddef>
#include <string>
namespace MalachScript {
class TextSpan {
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 !(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