Signed-off-by: erick-alcachofa <erick@artichoke.dev> This commit introduces the foundational structure for the parser and Abstract Syntax Tree (AST). It includes a new `Parser.hpp` header that outlines the primary parsing functions for top-level declarations like `modules`, `structs`, `enums`, and `functions`. It also adds a `toString` function for the AST to aid in debugging and visualization. The commit also updates the `Expected.hpp` utility by adding new error codes like `ecUnexpectedToken`, `ecExpectedSemicolon`, `ecImportInsideModule`, and `ecUnimplemented` to provide more granular and descriptive parsing errors. The `Tokenizer` has been updated to use these new, more specific exceptions.
111 lines
2.6 KiB
C++
111 lines
2.6 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,
|
|
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
|