#include #include #include #include using namespace std; #include "include/utils.h" #include "include/errors.h" #include "include/colors.h" #include "include/tokenize.h" string UserError::get_message(void) const { switch (this->type) { // Generic case ErrorType::NotImplemented: return "Not implemented"; // Lexing case ErrorType::UnknownToken: return "Unknown token"; case ErrorType::IntegerTooLarge: return "Integer constant is too large"; // Parsing case ErrorType::EmptyInput: return "Input must not be empty"; case ErrorType::InvalidSyntax: return "Invalid syntax"; case ErrorType::ExceptedLParen: return "Expected '("; case ErrorType::ExpectedRParen: return "Expected ')'"; case ErrorType::ExpectedLCurlyBracket: return "Expected '{'"; case ErrorType::ExpectedRCurlyBracket: return "Expected '}'"; case ErrorType::ExpectedSemicolon: return "Expected ';'"; case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration"; case ErrorType::NameOmitted: return "Omitting parameter name in a function definition"; // Flow control case ErrorType::BreakNotWithinLoop: return "Break statement not within loop"; case ErrorType::ContinueNotWithinLoop: return "Continue statement not within loop"; case ErrorType::ControlReachesEndOfNonVoidFn: return "Control reaches end of non-void function"; case ErrorType::UnexpectedReturn: return "Return not within a function"; // Analysis case ErrorType::UnknownType: return "Unknown type '"+get(this->data)+"'"; case ErrorType::TypeNotCastable: return "Can't find an explicit cast to "+get(this->data)+"'"; case ErrorType::TypesNotComparable: return "Types not comparable"; case ErrorType::ExpectedIntegralType: return "Expression must have integral type"; case ErrorType::ExpectedArithmeticType: return "Expression must have arithmetic type"; case ErrorType::NestedFunction: return "Function definition is not allowed here"; case ErrorType::FunctionRedefinition: return "Redefinition of '"+get(this->data)+"'"; case ErrorType::IncompatibleRedefinition: return "Redefinition of '"+get(this->data)+"' as different kind of symbol"; case ErrorType::IncompatibleDefinition: return "Declaration of '"+get(this->data)+"' is incompatible with previous prototype"; case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get(this->data))+" arguments to function call"; case ErrorType::IncompatibleReturnValue: return "Return value type does not match the function type"; case ErrorType::IncompleteType: return "Incomplete type is not allowed"; // Runtime case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get(this->data)+"'"; case ErrorType::AlreadyDeclaredIdentifier: return "Already declared identifier '"+get(this->data)+"'"; case ErrorType::UninitializedIdentifier: return "Accessing uninitialized identifier '"+get(this->data)+"'"; case ErrorType::DivisionByZero: return "Division by 0"; case ErrorType::ModuloByZero: return "Modulo by 0"; default: return "Unknown error type"; } } void print_error_position(vector history, CodePosition pos) { if (pos.column == -1 || pos.line == -1) return; cout << endl << BOLD << setw(4) << setfill(' ') << pos.line+1 << " " RESET << history[pos.line] << endl; for (int i=0; i < pos.column + 5; i++) cout << " "; cout << BOLD RED "^--" RESET << endl; } void print_error_stack_trace(vector history, const RuntimeError& error) { cout << "\n" BOLD "Traceback" RESET " (most recent call last)" << endl; for (StackTraceEntry e : error.trace) { cout << BOLD << setw(8) << setfill(' ') << to_string(get<1>(e).line+1) + ":" + to_string(get<1>(e).column+1) << RESET BLUE << setw(16) << setfill(' ') << get<0>(e) << RESET << " \t" << trim(history[get<1>(e).line]) << endl; } cout << BOLD RED "Runtime Error: " RESET << error.get_message() << endl; }