erick-alcachofa 552cda58e7
feat(Parser): Introduce AST toString and basic parser structure
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.
2025-10-15 16:12:19 -06:00

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