New error system

This commit is contained in:
ala89 2023-12-15 14:11:44 +01:00
parent 8e853aaaf2
commit eb29c03359
7 changed files with 89 additions and 69 deletions

View File

@ -9,7 +9,7 @@ bool bool_castable(AnalysisResult type) {
void check_comparable(AnalysisResult res1, AnalysisResult res2, CodePosition pos) {
if (holds_alternative<monostate>(res1) || holds_alternative<monostate>(res2)) {
throw TypeError("Incomparable values", pos);
throw TypeError(ErrorType::TypesNotComparable, pos);
}
Type type1 = get<Type>(res1);
@ -25,11 +25,11 @@ void check_comparable(AnalysisResult res1, AnalysisResult res2, CodePosition pos
return;
}
default:
throw TypeError("Incomparable values", pos);
throw TypeError(ErrorType::TypesNotComparable, pos);
}
}
default:
throw TypeError("Incomparable values", pos);
throw TypeError(ErrorType::TypesNotComparable, pos);
}
}
@ -53,7 +53,7 @@ Type try_string_to_type(string type_name, CodePosition pos) {
Type type = string_to_type(type_name);
return type;
} catch (...) {
throw TypeError("Unknown type '"+type_name+"'", pos);
throw TypeError(ErrorType::UnknownType, pos, type_name);
}
}
@ -74,7 +74,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data);
if (!memory.contains(identifier))
throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos);
throw RuntimeError(ErrorType::UnknownIdentifier, token.pos, identifier);
return memory.get(identifier).type;
throw exception();
@ -100,7 +100,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
case NodeType::If:
case NodeType::IfElse: {
if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[0]));
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
}
analyze(node.children[1], memory);
@ -111,7 +111,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
} break;
case NodeType::While: {
if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find a cast to bool", get_node_pos(node.children[0]));
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
}
analyze(node.children[1], memory);
@ -123,7 +123,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
analyze(node.children[0], memory);
if (!bool_castable(analyze(node.children[1], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[1]));
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
}
analyze(node.children[2], memory);
@ -142,17 +142,17 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
case NodeType::Lor:
case NodeType::Land: {
if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[0]));
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
}
if (!bool_castable(analyze(node.children[1], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[1]));
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
}
return Type::Int;
} break;
case NodeType::Neg: {
if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[0]));
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
}
return Type::Int;
@ -184,10 +184,10 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
AnalysisResult e2 = analyze(node.children[1], memory);
if (holds_alternative<monostate>(e1) || get<Type>(e1) != Type::Int) {
throw TypeError("Expression must have integral type", get_node_pos(node.children[0]));
throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[0]));
}
if (holds_alternative<monostate>(e2) || get<Type>(e2) != Type::Int) {
throw TypeError("Expression must have integral type", get_node_pos(node.children[1]));
throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[1]));
}
return Type::Int;
@ -197,7 +197,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
AnalysisResult res = analyze(node.children[0], memory);
if (holds_alternative<monostate>(res) || !is_arithmetic_type(get<Type>(res))) {
throw TypeError("Expressions must have arithmetic type", get_node_pos(node.children[1]));
throw TypeError(ErrorType::ExpectedArithmeticType, get_node_pos(node.children[0]));
}
return get<Type>(res);
@ -210,7 +210,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data);
if (memory.contains_top(identifier))
throw RuntimeError("Already defined identifier \""+identifier+"\"", token.pos);
throw RuntimeError(ErrorType::AlreadyDefinedIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type);
@ -225,7 +225,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data);
if (memory.contains_top(identifier))
throw TypeError("Already defined identifier \""+identifier+"\"", token.pos);
throw RuntimeError(ErrorType::AlreadyDefinedIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type);
@ -238,7 +238,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier))
throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
throw RuntimeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
Type type = memory.get(identifier).type;
AnalysisResult res = analyze(node.children[1], memory);
@ -255,7 +255,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier))
throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
throw RuntimeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
return memory.get(identifier).type;
}

View File

@ -12,20 +12,16 @@ using namespace std;
*/
EvalResult eval(Node &ast, Memory& memory);
class BreakException : public runtime_error {
class BreakException : public InternalError {
public:
explicit BreakException(const string& message, CodePosition pos)
: runtime_error(message), pos(pos) {}
const CodePosition pos;
explicit BreakException(CodePosition pos)
: InternalError(pos) {}
};
class ContinueException : public runtime_error {
class ContinueException : public InternalError {
public:
explicit ContinueException(const string& message, CodePosition pos)
: runtime_error(message), pos(pos) {}
const CodePosition pos;
explicit ContinueException(CodePosition pos)
: InternalError(pos) {}
};
#endif

View File

@ -10,10 +10,10 @@ using namespace std;
/**
* Utilisé pour revenir en arrière quand quelque chose n'est pas reconnu
*/
class ParseException : public std::exception {
const char* what() const noexcept override {
return "Parse Exception";
}
class ParseException : public InternalError {
public:
explicit ParseException(CodePosition pos = {})
: InternalError(pos) {}
};
/**

View File

@ -183,26 +183,50 @@ struct Scope {
/**
* Errors
*/
class SyntaxError : public runtime_error {
enum class ErrorType { DivisionByZero, ModuloByZero, ExpectedIntegralType, ExpectedArithmeticType, UninitializedIdentifier, UnknownIdentifier, AlreadyDefinedIdentifier, EmptyInput, UnknownToken, InvalidSyntax, ExceptedLParen, ExpectedRParen, ExpectedRCurlyBracket, ExpectedSemicolon, DependentDeclaration, TypesNotComparable, TypeNotCastable, UnknownType };
using ErrorData = variant<monostate, string>;
class UserError : public exception {
public:
explicit SyntaxError(const string& message, CodePosition pos)
: runtime_error(message), pos(pos) {}
explicit UserError(ErrorType type, CodePosition pos, ErrorData data = {})
: pos(pos), type(type), data(data) {}
const char* what() const noexcept override {
return "User error occurred.";
}
const CodePosition pos;
const ErrorType type;
const ErrorData data;
};
class TypeError : public runtime_error {
class SyntaxError : public UserError {
public:
explicit TypeError(const string& message, CodePosition pos)
: runtime_error(message), pos(pos) {}
const CodePosition pos;
explicit SyntaxError(ErrorType type, CodePosition pos, ErrorData data = {})
: UserError(type, pos, data) {}
};
class RuntimeError : public runtime_error {
class TypeError : public UserError {
public:
explicit RuntimeError(const string& message, CodePosition pos)
: runtime_error(message), pos(pos) {}
explicit TypeError(ErrorType type, CodePosition pos, ErrorData data = {})
: UserError(type, pos, data) {}
};
class RuntimeError : public UserError {
public:
explicit RuntimeError(ErrorType type, CodePosition pos, ErrorData data = {})
: UserError(type, pos, data) {}
};
class InternalError : public exception {
public:
explicit InternalError(CodePosition pos = {})
: pos(pos) {}
const char* what() const noexcept override {
return "Internal error occurred.";
}
const CodePosition pos;
};

View File

@ -241,13 +241,13 @@ EvalResult eval(Node &ast, Memory &memory) {
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
double d1 = double_cast(e1);
double d2 = double_cast(e2);
if (d2 == 0) throw RuntimeError("Division by 0", node.pos);
if (d2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos);
return d1 / d2;
}
else {
int i1 = get<int>(e1);
int i2 = get<int>(e2);
if (i2 == 0) throw RuntimeError("Division by 0", node.pos);
if (i2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos);
return i1 / i2;
}
} break;
@ -257,7 +257,7 @@ EvalResult eval(Node &ast, Memory &memory) {
int i1 = get<int>(e1);
int i2 = get<int>(e2);
if (i2 == 0) throw RuntimeError("Modulo by 0", node.pos);
if (i2 == 0) throw RuntimeError(ErrorType::ModuloByZero, node.pos);
return i1 % i2;
} break;
case NodeType::UnaryPlus: {
@ -332,7 +332,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
}
else if (var.type == Type::Int) {
memory.update(identifier, get<int>(var.value) + 1);
@ -349,7 +349,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
}
else if (var.type == Type::Int) {
int oldVal = get<int>(var.value);
@ -367,7 +367,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
}
else if (var.type == Type::Int) {
memory.update(identifier, get<int>(var.value) - 1);
@ -384,7 +384,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
}
else if (var.type == Type::Int) {
int oldVal = get<int>(var.value);
@ -396,7 +396,7 @@ EvalResult eval(Node &ast, Memory &memory) {
}
}
default: {
throw RuntimeError("Not Implemented", node.pos);
throw exception();
}
}
}
@ -419,15 +419,15 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized)
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos);
throw RuntimeError(ErrorType::UninitializedIdentifier, token.pos, identifier);
return var.value;
} break;
case TokenType::Break: {
throw BreakException("", token.pos);
throw BreakException(token.pos);
} break;
case TokenType::Continue: {
throw ContinueException("", token.pos);
throw ContinueException(token.pos);
} break;
default:
throw exception();

View File

@ -55,14 +55,14 @@ Node parse(vector<Token> tokens) {
reverse(tokens.begin(), tokens.end());
if (tokens.size() == 0) {
throw SyntaxError("Input must not be empty", null_pos);
throw SyntaxError(ErrorType::EmptyInput, null_pos);
}
ParseReturn ret = parse_prog(tokens);
if (ret.tokens.size() != 0) {
CodePosition pos = ret.tokens.back().pos;
throw SyntaxError("Unable to parse", pos);
throw SyntaxError(ErrorType::InvalidSyntax, pos);
}
return ret.node;
@ -169,7 +169,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back();
if (tokens.back().type != TokenType::Semicolon)
throw SyntaxError("Expected ';'", tokens.back().pos);
throw SyntaxError(ErrorType::ExpectedSemicolon, tokens.back().pos);
tokens.pop_back();
return {
@ -195,7 +195,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back();
if (tokens.back().type != TokenType::LParenthese) // Opening (
throw SyntaxError("Missing '('", tokens.back().pos);
throw SyntaxError(ErrorType::ExceptedLParen, tokens.back().pos);
tokens.pop_back();
ParseReturn ret = parse_expr(tokens); // Expr
@ -203,7 +203,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
int nb_tok = ret.tokens.size(); // Closing )
if (nb_tok == 0 || ret.tokens.back().type != TokenType::RParenthese)
throw SyntaxError(
"Missing ')'",
ErrorType::ExpectedRParen,
nb_tok == 0 ? tokens.back().pos : ret.tokens.back().pos
);
@ -215,7 +215,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
ret = parse_instruction(tokens); // Instruction1
} catch (const ParseException& pex) {
throw SyntaxError(
"Invalid Syntax",
ErrorType::InvalidSyntax,
pos=tokens.back().pos
);
}
@ -224,7 +224,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
( get<InnerNode>(ret.node).type == NodeType::AssignedDeclaration ||
get<InnerNode>(ret.node).type == NodeType::Declaration ) )
throw SyntaxError(
"a dependent statement may not be a declaration",
ErrorType::DependentDeclaration,
pos=tokens.back().pos
);
@ -263,7 +263,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back();
if (tokens.back().type != TokenType::LParenthese) // Opening (
throw SyntaxError("Missing '('", tokens.back().pos);
throw SyntaxError(ErrorType::ExceptedLParen, tokens.back().pos);
tokens.pop_back();
ParseReturn ret1;
@ -283,7 +283,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
int nb_tok = ret1.tokens.size(); // First ;
if (nb_tok == 0 || ret1.tokens.back().type != TokenType::Semicolon)
throw SyntaxError(
"Expected ';'",
ErrorType::ExpectedSemicolon,
nb_tok == 0 ? tokens.back().pos : ret1.tokens.back().pos
);
tokens = ret1.tokens;
@ -302,7 +302,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
nb_tok = ret2.tokens.size(); // Second ;
if (nb_tok == 0 || ret2.tokens.back().type != TokenType::Semicolon)
throw SyntaxError(
"Expected ';'",
ErrorType::ExpectedSemicolon,
nb_tok == 0 ? tokens.back().pos : ret2.tokens.back().pos
);
tokens = ret2.tokens;
@ -321,7 +321,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
nb_tok = ret3.tokens.size(); // Closing )
if (nb_tok == 0 || ret3.tokens.back().type != TokenType::RParenthese)
throw SyntaxError(
"Missing ')'",
ErrorType::ExpectedRParen,
nb_tok == 0 ? tokens.back().pos : ret3.tokens.back().pos
);
tokens = ret3.tokens;
@ -351,14 +351,14 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.back().type != TokenType::RCurlyBracket
)
throw SyntaxError(
"Invalid Syntax. Missing ';' ?",
ErrorType::InvalidSyntax,
tokens.back().pos
);
int nb_tok = ret.tokens.size();
if (nb_tok == 0 || ret.tokens.back().type != TokenType::RCurlyBracket)
throw SyntaxError(
"Missing '}'",
ErrorType::ExpectedRCurlyBracket,
nb_tok == 0 ? tokens.back().pos : ret.tokens.back().pos
);
@ -800,7 +800,7 @@ ParseReturn parse_val(vector<Token> tokens) {
tokens=ret.tokens;
if (tokens.size() < 1 || tokens.back().type != TokenType::RParenthese)
throw SyntaxError("Missing ')'", tokens.back().pos);
throw SyntaxError(ErrorType::ExpectedRParen, tokens.back().pos);
tokens.pop_back();

View File

@ -259,7 +259,7 @@ vector<Token> tokenize(vector<string> input, int initial_line) {
continue;
}
throw SyntaxError("Unknown token", pos);
throw SyntaxError(ErrorType::UnknownToken, pos);
}
}