erick-alcachofa 85a34bdd65
feat: Added Token, Tokenizer, Generator, and some utilities
Initial version of Tokenizer and Token
Generator template for coroutines (used in tokenizer)
Utilities like string related functions, TrieMap, and error handling

TODO: Add tests for Tokenizer
TODO: Add tests for Generator
2025-03-10 01:20:23 -06:00

85 lines
1.9 KiB
C++

#pragma once
#include <cstddef>
#include <string>
#include <expected>
#include <format>
namespace arti::lang {
enum struct ExceptCode {
ecEOF,
ecEOB,
ecInvalidToken,
ecStdException,
ecInvalidLiteral,
ecInvalidCharacter,
ecInvalidIndex,
};
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 {
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