Signed-off-by: erick-alcachofa <erick@artichoke.dev> This commit lays the foundational groundwork for the artichoke language parser by introducing the formal language grammar specification. The tokenizer was updated to include new operators and keywords, also added the posibility to handle comments. Key Additions: - Implemented support for C-style block comments (`/* ... */`), including error handling for unclosed comments. - Added all necessary tokens for missing keywords (e.g., `module`, `export`, `using`, `match`, `loop`) and operators (e.g., `+=`, `:=`, `.#`, `.*`, `.@`). - The `Token` enum has been expanded to reflect the full language feature set. Documentation: - Added `docs/grammar.ebnf` which contains the official, well-structured EBNF grammar for the language. - Added `docs/readme.md` providing a detailed technical overview of the language's features, syntax, and semantics. BREAKING CHANGE: The `kwVariant` and `kwMut` tokens have been removed to align with the updated language design defined in the new grammar.
89 lines
2.0 KiB
C++
89 lines
2.0 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,
|
|
ecInvalidComment,
|
|
};
|
|
|
|
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 {
|
|
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
|