Refactored error handling

Now uses base error class which has an abstract function for overiding how it is displayed to the console.
This commit is contained in:
Pasha Bibko
2025-05-05 15:44:59 +01:00
parent a16ce34c8b
commit 616ed1ca21
26 changed files with 340 additions and 243 deletions

View File

@@ -1,5 +1,7 @@
#include <Parser.h>
#include <ThrowIf.h>
#include <LLVM.h>
#include <Util.h>
#include <AST.h>

View File

@@ -1,5 +1,7 @@
#include <Parser.h>
#include <ThrowIf.h>
#include <Util.h>
#include <AST.h>
@@ -28,7 +30,7 @@ namespace LX
// Generates the IR within the function by looping over the nodes //
for (auto& node : funcAST.body)
{
ThrowIf<int>(IsValidTopLevelNode(node->m_Type) == false); // <- TODO: replace with actual error type
ThrowIf<IRGenerationError>(IsValidTopLevelNode(node->m_Type) == false); // <- TODO: replace with actual error type
node->GenIR(LLVM);
}
@@ -39,7 +41,7 @@ namespace LX
}
// Verifies the function works //
ThrowIf<int>(llvm::verifyFunction(*func)); // <- TODO: Make error type
ThrowIf<IRGenerationError>(llvm::verifyFunction(*func)); // <- TODO: Make error type
}
// Turns an abstract binary tree into LLVM intermediate representation //
@@ -55,8 +57,6 @@ namespace LX
// Loops over the functions to generate their LLVM IR //
for (auto& func : ast.functions)
{
std::cout << "\t|\t|- Generating function: " << func.name << "\n";
LLVM.scope = &func.scope; // Sets the current scope for the builder
GenerateFunctionIR(func, LLVM);
}

View File

@@ -1,5 +1,6 @@
#include <Parser.h>
#include <ThrowIf.h>
#include <Util.h>
#include <AST.h>
@@ -7,6 +8,9 @@
namespace LX
{
std::string* UnexpectedToken::s_Source = nullptr;
std::filesystem::path* UnexpectedToken::s_SourceFile = nullptr;
// Util function for working out if a token is a two sided operator //
static bool IsTwoSidedOperator(Token::TokenType t)
{
@@ -204,7 +208,7 @@ namespace LX
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log)
{
// Logs the start of the parsing
SafeLog(log, LOG_BREAK, "Started parsing tokens", LOG_BREAK);
SafeLog(log, LOG_BREAK, "Started parsing tokens", LOG_BREAK);
// Creates the output storer and the parser //
FileAST output;

View File

@@ -0,0 +1,78 @@
#include <Parser.h>
#include <Console.h>
#include <filesystem>
#include <iomanip>
#include <sstream>
namespace LX
{
void IRGenerationError::PrintToConsole() const
{
}
const char* IRGenerationError::ErrorType() const
{
return "IR Generation Error";
}
UnexpectedToken::UnexpectedToken(Token::TokenType _expected, std::string _override, Token _got)
: expected(_expected), override(_override), got(_got)
{}
void UnexpectedToken::PrintToConsole() const
{
// Calculates the length of the line number in the console so it is formatted correctly //
std::ostringstream oss;
oss << std::setw(3) << got.line;
size_t lineNumberWidthInConsole = std::max(oss.str().size(), (size_t)3);
// Gets the line of the error //
std::string line = LX::GetLineAtIndexOf(*s_Source, got.index);
// Prints the error to the console with the relevant info //
std::cout << "\n";
LX::PrintStringAsColor("Error: ", LX::Color::LIGHT_RED);
std::cout << "Incorrect syntax in ";
LX::PrintStringAsColor(s_SourceFile->filename().string(), LX::Color::WHITE);
std::cout << ", found ";
LX::PrintStringAsColor(LX::ToString(got.type).c_str(), LX::Color::WHITE);
std::cout << " expected: ";
// Allows the error to have a custom type that is printed to the console //
if (expected == LX::Token::UNDEFINED) { LX::PrintStringAsColor(override.c_str(), LX::Color::WHITE); }
else { LX::PrintStringAsColor(LX::ToString(expected).c_str(), LX::Color::WHITE); }
std::cout << "\n";
// Prints the code with the error to the console //
std::string errorSquiggle(got.length, '~');
std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << got.line << " | " << line << "\n";
std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(got.column) << "";
LX::PrintStringAsColor(errorSquiggle.c_str(), LX::Color::LIGHT_RED);
std::cout << "\n";
}
const char* UnexpectedToken::ErrorType() const
{
return "Unexpected Token";
}
void Scope::VariableAlreadyExists::PrintToConsole() const
{
}
const char* Scope::VariableAlreadyExists::ErrorType() const
{
return "Variable Already Exists";
}
void Scope::VariableDoesntExist::PrintToConsole() const
{
}
const char* Scope::VariableDoesntExist::ErrorType() const
{
return "Variable Doesn't exist";
}
}

View File

@@ -1,5 +1,6 @@
#include <Parser.h>
#include <ThrowIf.h>
#include <Util.h>
#include <AST.h>