133 lines
4.3 KiB
C++
133 lines
4.3 KiB
C++
//============================================================================//
|
|
// //
|
|
// artichoke programming language //
|
|
// //
|
|
// Copyright (C) 2025 Erick Saul Guzman Ramos, whoami.artichoke.dev //
|
|
// //
|
|
// //
|
|
// This program is free software: you can redistribute it and/or modify //
|
|
// it under the terms of the GNU Affero General Public License as published //
|
|
// by the Free Software Foundation, either version 3 of the License, or //
|
|
// (at your option) any later version. //
|
|
// //
|
|
// This program is distributed in the hope that it will be useful, //
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
// GNU Affero General Public License for more details. //
|
|
// //
|
|
// You should have received a copy of the GNU Affero General Public License //
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
|
|
// //
|
|
//============================================================================//
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
|
|
#include <string>
|
|
#include <expected>
|
|
#include <format>
|
|
|
|
namespace arti::lang {
|
|
|
|
enum struct ExceptCode {
|
|
ecEOF,
|
|
ecEOB,
|
|
ecInvalidToken,
|
|
ecStdException,
|
|
ecInvalidLiteral,
|
|
ecInvalidCharacter,
|
|
ecInvalidIndex,
|
|
ecInvalidComment,
|
|
ecUnexpectedToken,
|
|
ecExpectedSemicolon,
|
|
ecImportInsideModule,
|
|
ecUnimplemented,
|
|
};
|
|
|
|
struct Exception {
|
|
size_t line;
|
|
size_t column;
|
|
std::string message;
|
|
};
|
|
|
|
template <typename T, typename E = Exception>
|
|
using Expected = std::expected<T, E>;
|
|
|
|
template <typename E = Exception>
|
|
using Unexpected = std::unexpected<E>;
|
|
|
|
template <ExceptCode code, typename... Args>
|
|
std::string exceptionMessage(Args &&...args) {
|
|
using enum ExceptCode;
|
|
|
|
if constexpr (code == ecEOF) {
|
|
return "Reached EOF";
|
|
}
|
|
else if constexpr (code == ecEOB) {
|
|
return "Buffer empty";
|
|
}
|
|
else if constexpr (code == ecStdException) {
|
|
return std::format(
|
|
"Catched instance of {}: '{}'",
|
|
std::forward<Args>(args)...
|
|
);
|
|
}
|
|
else if constexpr (code == ecInvalidLiteral) {
|
|
return std::format(
|
|
"Invalid literal, expected {} got {}",
|
|
std::forward<Args>(args)...
|
|
);
|
|
}
|
|
else if constexpr (code == ecInvalidCharacter) {
|
|
return std::format(
|
|
"Invalid character found '{}'",
|
|
std::forward<Args>(args)...
|
|
);
|
|
}
|
|
else if constexpr (code == ecInvalidToken) {
|
|
return std::format(
|
|
"Invalid token found '{}'",
|
|
std::forward<Args>(args)...
|
|
);
|
|
}
|
|
else if constexpr (code == ecInvalidIndex) {
|
|
return "Invalid index";
|
|
}
|
|
else if constexpr (code == ecInvalidComment) {
|
|
return "Invalid comment found, missing '*/' end of comment";
|
|
}
|
|
else if constexpr (code == ecUnexpectedToken) {
|
|
return std::format(
|
|
"Found unexpected token '{}', expected {}",
|
|
std::forward<Args>(args)...
|
|
);
|
|
}
|
|
else if constexpr (code == ecExpectedSemicolon) {
|
|
return std::format(
|
|
"Expected ';', got '{}'",
|
|
std::forward<Args>(args)...
|
|
);
|
|
}
|
|
else if constexpr (code == ecImportInsideModule) {
|
|
return "Cannot use import statements inside a module declaration";
|
|
}
|
|
else if constexpr (code == ecUnimplemented) {
|
|
return "Unimplemented";
|
|
}
|
|
else {
|
|
return "Unknown error";
|
|
}
|
|
}
|
|
|
|
template <ExceptCode code, typename... Args>
|
|
static inline Unexpected<>
|
|
langException(size_t line, size_t col, Args &&...args) {
|
|
return Unexpected{
|
|
Exception{ line,
|
|
col, exceptionMessage<code>(std::forward<Args>(args)...) }
|
|
};
|
|
}
|
|
|
|
} // namespace arti::lang
|