//============================================================================//
// //
// 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 . //
// //
//============================================================================//
#pragma once
#include
#include
#include
#include
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
using Expected = std::expected;
template
using Unexpected = std::unexpected;
template
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)...
);
}
else if constexpr (code == ecInvalidLiteral) {
return std::format(
"Invalid literal, expected {} got {}",
std::forward(args)...
);
}
else if constexpr (code == ecInvalidCharacter) {
return std::format(
"Invalid character found '{}'",
std::forward(args)...
);
}
else if constexpr (code == ecInvalidToken) {
return std::format(
"Invalid token found '{}'",
std::forward(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)...
);
}
else if constexpr (code == ecExpectedSemicolon) {
return std::format(
"Expected ';', got '{}'",
std::forward(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
static inline Unexpected<>
langException(size_t line, size_t col, Args &&...args) {
return Unexpected{
Exception{ line,
col, exceptionMessage(std::forward(args)...) }
};
}
} // namespace arti::lang