diff --git a/repl/main.cpp b/repl/main.cpp index 6c5d2e0..7312aa6 100644 --- a/repl/main.cpp +++ b/repl/main.cpp @@ -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& formats) { logger.Log(level, type, "", span, formats); }; + const MalachScript::ScriptTextSpan& span, + const std::vector& formats) { logger.Log(level, type, span, formats); }; MalachScript::Binder::Binder::Bind(ns, {parsedResult}, log); const MalachScript::Diagnostics::Diagnostic* diag = nullptr; diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 84c6170..24ef19e 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -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& 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(inherits), stack, log); + } + size += inherits->GetSize(); + } + for (auto& field : type->GetFieldsLookup()) { + if (!field.second->GetType()->IsInitialised()) { + FinaliseType(const_cast(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 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); diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index 31232b8..8f9bd54 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -10,7 +10,7 @@ namespace MalachScript::Binder { class Binder { public: using log_func = const std::function&)>; + const ScriptTextSpan&, const std::vector&)>; static void Bind(BoundNamespace* ns, const std::vector& statements, diff --git a/src/Binder/BoundType.hpp b/src/Binder/BoundType.hpp index 89e718c..f5bd68b 100644 --- a/src/Binder/BoundType.hpp +++ b/src/Binder/BoundType.hpp @@ -1,34 +1,30 @@ #ifndef MALACHSCRIPT_BOUNDTYPE_HPP #define MALACHSCRIPT_BOUNDTYPE_HPP +#include #include +#include +#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&)>; - inline void Finalise() noexcept { - if (_initialised) { - return; - } + BoundType(Identifier identifier, ClassAttr classAttr, std::optional 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(inherits)->Finalise(); - } - _size += inherits->GetSize(); - } - for (auto& field : _fields) { - if (!field->GetType()->IsInitialised()) { - const_cast(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& GetFieldsLookup() const noexcept { return _fieldsLookup; } + [[nodiscard]] inline const std::vector& GetInherits() const noexcept { return _inherits; } - inline std::optional ResolveType(const Identifier& identifier) const noexcept { + [[nodiscard]] inline std::optional 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& GetSpan() const noexcept { return _span; } + private: bool _initialised = false; Identifier _identifier; ClassAttr _classAttr; + std::optional _span; + size_t _size = 0; std::vector _inherits; std::vector _fields; diff --git a/src/Binder/BoundVariable.hpp b/src/Binder/BoundVariable.hpp index 127bede..4644676 100644 --- a/src/Binder/BoundVariable.hpp +++ b/src/Binder/BoundVariable.hpp @@ -1,6 +1,8 @@ #ifndef MALACHSCRIPT_BOUNDVARIABLE_HPP #define MALACHSCRIPT_BOUNDVARIABLE_HPP +#include "../CoreData/AccessModifier.hpp" + namespace MalachScript::Binder { class BoundType; diff --git a/src/CoreData/ClassAttr.hpp b/src/CoreData/ClassAttr.hpp index 5906eee..195de45 100644 --- a/src/CoreData/ClassAttr.hpp +++ b/src/CoreData/ClassAttr.hpp @@ -1,6 +1,8 @@ #ifndef MALACHSCRIPT_CLASSATTR_HPP #define MALACHSCRIPT_CLASSATTR_HPP +#include + namespace MalachScript { enum class ClassAttr : uint8_t { None = 0, diff --git a/src/Diagnostics/DiagnosticType.hpp b/src/Diagnostics/DiagnosticType.hpp index 368a7be..b9d17ca 100644 --- a/src/Diagnostics/DiagnosticType.hpp +++ b/src/Diagnostics/DiagnosticType.hpp @@ -11,6 +11,7 @@ namespace MalachScript::Diagnostics { UnknownType, TypeAlreadyDefined, + CircularTypeReference, }; } diff --git a/src/Diagnostics/DiagnosticTypeEN_US.hpp b/src/Diagnostics/DiagnosticTypeEN_US.hpp index 3976305..fc45618 100644 --- a/src/Diagnostics/DiagnosticTypeEN_US.hpp +++ b/src/Diagnostics/DiagnosticTypeEN_US.hpp @@ -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()); } diff --git a/src/Diagnostics/Logger.hpp b/src/Diagnostics/Logger.hpp index 075a440..68dc01a 100644 --- a/src/Diagnostics/Logger.hpp +++ b/src/Diagnostics/Logger.hpp @@ -9,25 +9,29 @@ namespace MalachScript::Diagnostics { std::vector _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& 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& 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& formats = {}) { + Log(DiagnosticLevel::Information, type, span, formats); + } + inline void LogWarning(DiagnosticType type, const ScriptTextSpan& span, + const std::vector& formats = {}) { + Log(DiagnosticLevel::Warning, type, span, formats); + } + inline void LogError(DiagnosticType type, const ScriptTextSpan& span, + const std::vector& formats = {}) { + Log(DiagnosticLevel::Error, type, span, formats); + } + inline void LogCritical(DiagnosticType type, const ScriptTextSpan& span, + const std::vector& formats = {}) { + Log(DiagnosticLevel::Critical, type, span, formats); } [[nodiscard]] const std::vector& GetMessages() const noexcept { return _messages; } diff --git a/src/Parser/Lexer/LexToken.hpp b/src/Parser/Lexer/LexToken.hpp index 167df02..d3d4e40 100644 --- a/src/Parser/Lexer/LexToken.hpp +++ b/src/Parser/Lexer/LexToken.hpp @@ -11,14 +11,14 @@ namespace MalachScript::Parser { class LexToken { std::unique_ptr _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& 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(token); } @@ -26,7 +26,7 @@ namespace MalachScript::Parser { template 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(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(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(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(span), _value(value) {} [[nodiscard]] inline const Identifier& GetValue() const noexcept { return _value; } diff --git a/src/Parser/Lexer/Lexer.cpp b/src/Parser/Lexer/Lexer.cpp index 19fa076..3e430fc 100644 --- a/src/Parser/Lexer/Lexer.cpp +++ b/src/Parser/Lexer/Lexer.cpp @@ -25,7 +25,8 @@ namespace MalachScript::Parser { auto start = _position; auto c = Consume(); switch (c) { - case '\0': return Create>(TextSpan(start + 1, start + 2)); + case '\0': + return Create>(ScriptTextSpan(start + 1, start + 2, _scriptName)); case '*': { auto n = Peek(); if (n == '*') { @@ -34,71 +35,81 @@ namespace MalachScript::Parser { if (n == '=') { Progress(); // **= - return Create>(TextSpan(start, start + 3)); + return Create>( + ScriptTextSpan(start, start + 3, _scriptName)); } // ** - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '=') { Progress(); // *= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // * - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } case '/': if (Peek() == '=') { Progress(); // /= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // / - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); case '%': if (Peek() == '=') { Progress(); // %= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // % - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); case '+': { auto n = Peek(); if (n == '=') { Progress(); // += - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '+') { Progress(); // ++ - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // + - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } case '-': { auto n = Peek(); if (n == '=') { Progress(); // -= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '-') { Progress(); // -- - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // - - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } case '<': { auto n = Peek(); if (n == '=') { Progress(); // <= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '<') { Progress(); @@ -106,20 +117,23 @@ namespace MalachScript::Parser { Progress(); // <<= return Create>( - TextSpan(start, start + 3)); + ScriptTextSpan(start, start + 3, _scriptName)); } // << - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // < - return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); } case '>': { auto n = Peek(); if (n == '=') { Progress(); // >= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '>') { Progress(); @@ -128,7 +142,7 @@ namespace MalachScript::Parser { Progress(); // >>= return Create>( - TextSpan(start, start + 3)); + ScriptTextSpan(start, start + 3, _scriptName)); } if (n == '>') { Progress(); @@ -136,125 +150,159 @@ namespace MalachScript::Parser { Progress(); // >>>= return Create>( - TextSpan(start, start + 4)); + ScriptTextSpan(start, start + 4, _scriptName)); } // >>> return Create>( - TextSpan(start, start + 3)); + ScriptTextSpan(start, start + 3, _scriptName)); } // >> - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // > - return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); } - case '(': return Create>(TextSpan(start, start + 1)); - case ')': return Create>(TextSpan(start, start + 1)); + case '(': + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); + case ')': + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); case '=': { if (Peek() == '=') { Progress(); // == - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // = - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } case '!': { auto n = Peek(); if (n == '=') { Progress(); // != - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == 'i' && Peek(2) == 's') { Progress(2); // !is - return Create>(TextSpan(start, start + 3)); + return Create>( + ScriptTextSpan(start, start + 3, _scriptName)); } // ! - return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); } - case '?': return Create>(TextSpan(start, start + 1)); + case '?': + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); case ':': { if (Peek() == ':') { Progress(); // :: - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // : - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } case '&': { auto n = Peek(); if (n == '=') { Progress(); // &= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '&') { Progress(); // && - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // & - return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); } - case ',': return Create>(TextSpan(start, start + 1)); - case '{': return Create>(TextSpan(start, start + 1)); + case ',': + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); + case '{': + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); case '}': - return Create>(TextSpan(start, start + 1)); - case ';': return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); + case ';': + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); case '|': { auto n = Peek(); if (n == '=') { Progress(); // |= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '|') { Progress(); // || return Create>( - TextSpan(start, start + 2)); + ScriptTextSpan(start, start + 2, _scriptName)); } // | - return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); } case '^': { auto n = Peek(); if (n == '=') { Progress(); // ^= - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } if (n == '^') { Progress(); // ^^ - return Create>(TextSpan(start, start + 2)); + return Create>( + ScriptTextSpan(start, start + 2, _scriptName)); } // ^ - return Create>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } - case '~': return Create>(TextSpan(start, start + 1)); - case '.': return Create>(TextSpan(start, start + 1)); - case '[': return Create>(TextSpan(start, start + 1)); + case '~': + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); + case '.': + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); + case '[': + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); case ']': - return Create>(TextSpan(start, start + 1)); - case '@': return Create>(TextSpan(start, start + 1)); + return Create>( + ScriptTextSpan(start, start + 1, _scriptName)); + case '@': + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); case ' ': case '\r': case '\n': - case '\t': return Create>(TextSpan(start, start + 1)); + case '\t': + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); // Byte order mark case '\xEF': { if (Peek() == '\xBB' && Peek(2) == '\xBF') { Progress(2); - return Create>(TextSpan(start, start + 3)); + return Create>( + 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>(TextSpan(start, start + 1)); + return Create>(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>(TextSpan(start, start + 1)); + return Create>(ScriptTextSpan(start, start + 1, _scriptName)); } } @@ -311,7 +359,7 @@ namespace MalachScript::Parser { Progress(); numericalSystem = 2; break; - default: return Create(TextSpan(_position - 1, _position), 0); + default: return Create(ScriptTextSpan(_position - 1, _position, _scriptName), 0); } } } @@ -390,9 +438,9 @@ namespace MalachScript::Parser { if (isExponent) { val *= pow(10, exponentValue); } - return Create(TextSpan(start, _position), val); + return Create(ScriptTextSpan(start, _position, _scriptName), val); } - return Create(TextSpan(start, _position), value); + return Create(ScriptTextSpan(start, _position, _scriptName), value); } IntegerLiteral* Lexer::LexHexadecimal() { @@ -407,7 +455,7 @@ namespace MalachScript::Parser { value <<= 4; value += v; } - return Create(TextSpan(start - 1, _position), value); + return Create(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(TextSpan(start - 1, _position), value); + return Create(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(TextSpan(start - 1, _position), value); + return Create(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(TextSpan(openingPos, openingPos + _position), + return Create(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>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("abstract"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("auto"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("bool"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("break"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("case"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("cast"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("catch"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("class"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("const"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("continue"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("default"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("do"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("double"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("else"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("enum"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("explicit"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("external"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("false"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("final"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("float"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("for"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("from"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("funcdef"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("function"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("get"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("if"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("import"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("in"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("inout"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("int"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("interface"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("int8"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("int16"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("int32"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("int64"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("is"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("mixin"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("namespace"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("not"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("null"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("or"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("out"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("override"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("private"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("property"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("protected"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("return"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("set"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("shared"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("super"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("switch"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("this"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("true"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("try"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("typedef"): - return Create>(TextSpan(start, _position)); + return Create>( + ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("uint"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("uint8"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("uint16"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("uint32"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("uint64"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("void"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("while"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); case Identifier::Hash("xor"): - return Create>(TextSpan(start, _position)); + return Create>(ScriptTextSpan(start, _position, _scriptName)); - default: return Create(TextSpan(start, _position), Identifier(str.data(), offset, hash)); + default: + return Create(ScriptTextSpan(start, _position, _scriptName), + Identifier(str.data(), offset, hash)); } } bool Lexer::IsAlphaNumericalOrUnderscore(char c) { diff --git a/src/Parser/Lexer/Lexer.hpp b/src/Parser/Lexer/Lexer.hpp index 7b159e2..ea39c32 100644 --- a/src/Parser/Lexer/Lexer.hpp +++ b/src/Parser/Lexer/Lexer.hpp @@ -57,8 +57,9 @@ namespace MalachScript::Parser { return _allocator.Create(args...); } - inline void LogError(Diagnostics::DiagnosticType type, TextSpan span, const std::vector& formats) { - _diagnostics->LogError(type, _scriptName, span, formats); + inline void LogError(Diagnostics::DiagnosticType type, const ScriptTextSpan& span, + const std::vector& formats) { + _diagnostics->LogError(type, span, formats); } }; } diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 7ff4073..d056e75 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -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& 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& formats) { + diagnostics->Log(level, type, span, formats); }; ScopedPtr 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& 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,9 +291,10 @@ namespace MalachScript::Parser { } else { PROGRESS_TOKEN(current); } - out = new ParsedFuncStatement(TextSpan(start, current->GetSpan().GetEnd()), isShared, isExternal, - accessModifier, typeStatement.TakeOwnership(), returnsReference, identifier, - paramList.TakeOwnership(), isConst, funcAttr, statblock.TakeOwnership()); + 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& 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& out, const LexToken*& currentToken, + bool Parser::ParseVirtProp(ScopedPtr& 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,8 +685,10 @@ namespace MalachScript::Parser { logUnexpectedToken(CloseCurlyParenthesisSymbol, current); } - out = new ParsedStatBlockStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), - statements); + 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( - TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand.TakeOwnership(), op, - rightHand.TakeOwnership()); + out = new ParsedBinaryStatement(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,12 +825,16 @@ namespace MalachScript::Parser { // TODO: remainder of if (current->GetKind() == LexTokenKind::PlusPlusSymbol) { - operand = new ParsedIncrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()), - operand.TakeOwnership()); + 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.TakeOwnership()); + 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 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& out, const LexToken*& currentToken, @@ -913,7 +940,9 @@ namespace MalachScript::Parser { std::vector 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& 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& 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; diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp index daa9870..1d65e64 100644 --- a/src/Parser/Parser.hpp +++ b/src/Parser/Parser.hpp @@ -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&)>; + const ScriptTextSpan&, const std::vector&)>; ///////////////////////////////////////////////////////////////////////////////////////// // Underlying functions are laid out in the order they are defined in the grammar.ebnf // diff --git a/src/Parser/Statements/ParsedStatement.hpp b/src/Parser/Statements/ParsedStatement.hpp index 813ce86..e899df1 100644 --- a/src/Parser/Statements/ParsedStatement.hpp +++ b/src/Parser/Statements/ParsedStatement.hpp @@ -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 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> _statements; public: - ParsedScriptStatement(TextSpan span, const std::vector& statements) + ParsedScriptStatement(ScriptTextSpan span, const std::vector& statements) : ParsedStatementImpl(span), _statements(statements.size()) { for (size_t i = 0; i < statements.size(); i++) _statements[i] = std::unique_ptr(statements[i]); @@ -47,7 +47,7 @@ namespace MalachScript::Parser { class ParsedClassStatement : public ParsedStatementImpl { public: - ParsedClassStatement(TextSpan span, ClassAttr classAttr, Identifier identifier, + ParsedClassStatement(ScriptTextSpan span, ClassAttr classAttr, Identifier identifier, const std::vector& inherits, const std::vector& body) : ParsedStatementImpl(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(span), _defineFrom(defineFrom), _defineTo(defineTo) {} [[nodiscard]] inline const Identifier& GetDefineFrom() const noexcept { return _defineFrom; } @@ -87,7 +87,7 @@ namespace MalachScript::Parser { std::unique_ptr _parsedScript; public: - ParsedNamespaceStatement(TextSpan span, const Identifier& identifier, const ParsedScriptStatement* script) + ParsedNamespaceStatement(ScriptTextSpan span, const Identifier& identifier, const ParsedScriptStatement* script) : ParsedStatementImpl(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(span), _isConst(isConst), _isArray(isArray), _isHandle(isHandle), _scopedIdentifier(scopedIdentifier) {} @@ -155,7 +155,7 @@ namespace MalachScript::Parser { std::vector> _parameters; public: - ParsedParamListStatement(TextSpan span, const std::vector& parameters) + ParsedParamListStatement(ScriptTextSpan span, const std::vector& parameters) : ParsedStatementImpl(span), _parameters(parameters.size()) { for (size_t i = 0; i < parameters.size(); i++) { _parameters[i] = std::unique_ptr(parameters[i]); @@ -181,7 +181,7 @@ namespace MalachScript::Parser { std::unique_ptr _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 { 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 { public: - ParsedStatBlockStatement(const TextSpan& span, const std::vector& statements) + ParsedStatBlockStatement(const ScriptTextSpan& span, const std::vector& statements) : ParsedStatementImpl(span), _statements(statements.size()) { for (size_t i = 0; i < statements.size(); i++) { _statements[i] = std::unique_ptr(statements[i]); @@ -274,7 +274,7 @@ namespace MalachScript::Parser { class ParsedVarStatement : public ParsedStatementImpl { 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 { 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 ParsedBinaryStatement : public ParsedStatementImpl { 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 { public: - ParsedVoidStatement(const TextSpan& span) : ParsedStatementImpl(span) {} + ParsedVoidStatement(const ScriptTextSpan& span) : ParsedStatementImpl(span) {} }; template class ParsedLiteralStatement : public ParsedStatementImpl { 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 { 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 { public: - ParsedVarAccessStatement(const TextSpan& span, std::vector scope) + ParsedVarAccessStatement(const ScriptTextSpan& span, std::vector scope) : ParsedStatementImpl(span), _scope(std::move(scope)) {} private: @@ -361,7 +361,7 @@ namespace MalachScript::Parser { class ParsedIncrementStatement : public ParsedStatementImpl { 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 { 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 { public: - ParsedContinueStatement(const TextSpan& span) : ParsedStatementImpl(span) {} + ParsedContinueStatement(const ScriptTextSpan& span) : ParsedStatementImpl(span) {} }; class ParsedBreakStatement : public ParsedStatementImpl { public: - ParsedBreakStatement(const TextSpan& span) : ParsedStatementImpl(span) {} + ParsedBreakStatement(const ScriptTextSpan& span) : ParsedStatementImpl(span) {} }; class ParsedForStatement : public ParsedStatementImpl { public: - ParsedForStatement(const TextSpan& span, const ParsedStatement* init, const ParsedStatement* condition, + ParsedForStatement(const ScriptTextSpan& span, const ParsedStatement* init, const ParsedStatement* condition, std::vector 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 { 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 { 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 { 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 { public: - ParsedSwitchStatement(const TextSpan& span, const ParsedStatement* expression, + ParsedSwitchStatement(const ScriptTextSpan& span, const ParsedStatement* expression, const std::vector& 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 { public: - ParsedCaseStatement(const TextSpan& span, const ParsedStatement* expression, + ParsedCaseStatement(const ScriptTextSpan& span, const ParsedStatement* expression, const std::vector& statements) : ParsedStatementImpl(span), _expression(expression), _statements(statements.size()) { for (size_t i = 0; i < statements.size(); i++) { diff --git a/src/TextSpan.hpp b/src/TextSpan.hpp index 3621b46..cc16d53 100644 --- a/src/TextSpan.hpp +++ b/src/TextSpan.hpp @@ -2,6 +2,8 @@ #define MALACHSCRIPT_TEXTSPAN_HPP #include +#include + 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