Add ControlError class
This commit is contained in:
parent
1553df6328
commit
de3f9a49b5
@ -373,7 +373,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
try {
|
try {
|
||||||
memory.get_function_scope();
|
memory.get_function_scope();
|
||||||
} catch (const InternalError& _) {
|
} catch (const InternalError& _) {
|
||||||
throw RuntimeError(ErrorType::UnexpectedReturn, node.pos, {});
|
throw ControlError(ErrorType::UnexpectedReturn, node.pos, {});
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,14 @@ using namespace std;
|
|||||||
|
|
||||||
string UserError::get_message(void) const {
|
string UserError::get_message(void) const {
|
||||||
switch (this->type) {
|
switch (this->type) {
|
||||||
|
// Generic
|
||||||
case ErrorType::NotImplemented: return "Not implemented";
|
case ErrorType::NotImplemented: return "Not implemented";
|
||||||
|
|
||||||
|
// Lexing
|
||||||
case ErrorType::UnknownToken: return "Unknown token";
|
case ErrorType::UnknownToken: return "Unknown token";
|
||||||
case ErrorType::IntegerTooLarge: return "Integer constant is too large";
|
case ErrorType::IntegerTooLarge: return "Integer constant is too large";
|
||||||
|
|
||||||
|
// Parsing
|
||||||
case ErrorType::EmptyInput: return "Input must not be empty";
|
case ErrorType::EmptyInput: return "Input must not be empty";
|
||||||
case ErrorType::InvalidSyntax: return "Invalid syntax";
|
case ErrorType::InvalidSyntax: return "Invalid syntax";
|
||||||
case ErrorType::ExceptedLParen: return "Expected '(";
|
case ErrorType::ExceptedLParen: return "Expected '(";
|
||||||
@ -20,25 +25,31 @@ string UserError::get_message(void) const {
|
|||||||
case ErrorType::ExpectedRCurlyBracket: return "Expected '}'";
|
case ErrorType::ExpectedRCurlyBracket: return "Expected '}'";
|
||||||
case ErrorType::ExpectedSemicolon: return "Expected ';'";
|
case ErrorType::ExpectedSemicolon: return "Expected ';'";
|
||||||
case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration";
|
case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration";
|
||||||
|
|
||||||
|
// 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";
|
||||||
|
|
||||||
|
// Analysus
|
||||||
case ErrorType::UnknownType: return "Unknown type '"+get<string>(this->data)+"'";
|
case ErrorType::UnknownType: return "Unknown type '"+get<string>(this->data)+"'";
|
||||||
case ErrorType::TypeNotCastable: return "Can't find an explicit cast to "+get<string>(this->data)+"'";
|
case ErrorType::TypeNotCastable: return "Can't find an explicit cast to "+get<string>(this->data)+"'";
|
||||||
case ErrorType::TypesNotComparable: return "Types not comparable";
|
case ErrorType::TypesNotComparable: return "Types not comparable";
|
||||||
case ErrorType::ExpectedIntegralType: return "Expression must have integral type";
|
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::NestedFunction: return "Function definition is not allowed here";
|
||||||
case ErrorType::FunctionRedefinition: return "Redefinition of '"+get<string>(this->data)+"'";
|
case ErrorType::FunctionRedefinition: return "Redefinition of '"+get<string>(this->data)+"'";
|
||||||
case ErrorType::IncompatibleRedefinition: return "Redefinition of '"+get<string>(this->data)+"' as different kind of symbol";
|
case ErrorType::IncompatibleRedefinition: return "Redefinition of '"+get<string>(this->data)+"' as different kind of symbol";
|
||||||
case ErrorType::IncompatibleDefinition: return "Declaration of '"+get<string>(this->data)+"' is incompatible with previous prototype";
|
case ErrorType::IncompatibleDefinition: return "Declaration of '"+get<string>(this->data)+"' is incompatible with previous prototype";
|
||||||
case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get<int>(this->data))+" arguments to function call";
|
case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get<int>(this->data))+" arguments to function call";
|
||||||
case ErrorType::UnexpectedReturn: return "Return not within a function";
|
|
||||||
case ErrorType::ExpectedArithmeticType: return "Expression must have arithmetic type";
|
// Runtime
|
||||||
case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get<string>(this->data)+"'";
|
case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get<string>(this->data)+"'";
|
||||||
case ErrorType::AlreadyDeclaredIdentifier: return "Already declared identifier '"+get<string>(this->data)+"'";
|
case ErrorType::AlreadyDeclaredIdentifier: return "Already declared identifier '"+get<string>(this->data)+"'";
|
||||||
case ErrorType::UninitializedIdentifier: return "Accessing uninitialized identifier '"+get<string>(this->data)+"'";
|
case ErrorType::UninitializedIdentifier: return "Accessing uninitialized identifier '"+get<string>(this->data)+"'";
|
||||||
case ErrorType::DivisionByZero: return "Division by 0";
|
case ErrorType::DivisionByZero: return "Division by 0";
|
||||||
case ErrorType::ModuloByZero: return "Modulo by 0";
|
case ErrorType::ModuloByZero: return "Modulo by 0";
|
||||||
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";
|
|
||||||
default: return "Unknown error type";
|
default: return "Unknown error type";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@ EvalResult execute(vector<string> input, Memory& memory, int initial_line, ExecA
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
} catch (const BreakException& except) {
|
} catch (const BreakException& except) {
|
||||||
throw RuntimeError(ErrorType::BreakNotWithinLoop, except.pos);
|
throw ControlError(ErrorType::BreakNotWithinLoop, except.pos);
|
||||||
} catch (const ContinueException& except) {
|
} catch (const ContinueException& except) {
|
||||||
throw RuntimeError(ErrorType::ContinueNotWithinLoop, except.pos);
|
throw ControlError(ErrorType::ContinueNotWithinLoop, except.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,6 +27,12 @@ enum class ErrorType {
|
|||||||
ExpectedSemicolon,
|
ExpectedSemicolon,
|
||||||
DependentDeclaration,
|
DependentDeclaration,
|
||||||
|
|
||||||
|
// Flow control
|
||||||
|
BreakNotWithinLoop,
|
||||||
|
ContinueNotWithinLoop,
|
||||||
|
ControlReachesEndOfNonVoidFn,
|
||||||
|
UnexpectedReturn,
|
||||||
|
|
||||||
// Analysis
|
// Analysis
|
||||||
UnknownType,
|
UnknownType,
|
||||||
TypeNotCastable,
|
TypeNotCastable,
|
||||||
@ -38,17 +44,13 @@ enum class ErrorType {
|
|||||||
IncompatibleRedefinition, // redefinition of a variable as a function
|
IncompatibleRedefinition, // redefinition of a variable as a function
|
||||||
IncompatibleDefinition, // function declaration incompatible with prototype
|
IncompatibleDefinition, // function declaration incompatible with prototype
|
||||||
UnexpectedArgumentCount,
|
UnexpectedArgumentCount,
|
||||||
UnexpectedReturn,
|
|
||||||
|
|
||||||
// Runtime
|
// Runtime
|
||||||
UnknownIdentifier,
|
UnknownIdentifier,
|
||||||
AlreadyDeclaredIdentifier,
|
AlreadyDeclaredIdentifier,
|
||||||
UninitializedIdentifier,
|
UninitializedIdentifier,
|
||||||
DivisionByZero,
|
DivisionByZero,
|
||||||
ModuloByZero,
|
ModuloByZero
|
||||||
BreakNotWithinLoop,
|
|
||||||
ContinueNotWithinLoop,
|
|
||||||
ControlReachesEndOfNonVoidFn
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using ErrorData = variant<monostate, string, int>;
|
using ErrorData = variant<monostate, string, int>;
|
||||||
@ -75,6 +77,12 @@ public:
|
|||||||
: UserError(type, pos, data) {}
|
: UserError(type, pos, data) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ControlError : public UserError {
|
||||||
|
public:
|
||||||
|
explicit ControlError(ErrorType type, CodePosition pos, ErrorData data = {})
|
||||||
|
: UserError(type, pos, data) {}
|
||||||
|
};
|
||||||
|
|
||||||
class TypeError : public UserError {
|
class TypeError : public UserError {
|
||||||
public:
|
public:
|
||||||
explicit TypeError(ErrorType type, CodePosition pos, ErrorData data = {})
|
explicit TypeError(ErrorType type, CodePosition pos, ErrorData data = {})
|
||||||
|
@ -212,7 +212,7 @@ EvalResult eval(Node &ast, Memory &memory) {
|
|||||||
|
|
||||||
// Tmp: no flow control
|
// Tmp: no flow control
|
||||||
if (get<0>(prototype[0]).type != TypeType::Void) {
|
if (get<0>(prototype[0]).type != TypeType::Void) {
|
||||||
throw RuntimeError(ErrorType::ControlReachesEndOfNonVoidFn, identifierTok.pos);
|
throw ControlError(ErrorType::ControlReachesEndOfNonVoidFn, identifierTok.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const ReturnException& e) {
|
catch (const ReturnException& e) {
|
||||||
|
@ -110,6 +110,10 @@ int main(int argc, char* argv[]) {
|
|||||||
print_error_position(input, e.pos);
|
print_error_position(input, e.pos);
|
||||||
cout << BOLD RED "Syntax Error: " RESET << e.get_message() << endl;
|
cout << BOLD RED "Syntax Error: " RESET << e.get_message() << endl;
|
||||||
|
|
||||||
|
} catch (const ControlError& e) {
|
||||||
|
print_error_position(input, e.pos);
|
||||||
|
cout << BOLD RED "Control Error: " RESET << e.get_message() << endl;
|
||||||
|
|
||||||
} catch (const TypeError& e) {
|
} catch (const TypeError& e) {
|
||||||
print_error_position(input, e.pos);
|
print_error_position(input, e.pos);
|
||||||
cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;
|
cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user