Skip to content

Commit

Permalink
catching out of bounds integer literals and division by zero errors
Browse files Browse the repository at this point in the history
  • Loading branch information
mgerhold committed Nov 11, 2023
1 parent c59bba1 commit 930603b
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_executable(
lexer.hpp
lexer.cpp
token.hpp
token.cpp
overloaded.hpp
parser.cpp
parser.hpp
Expand Down
11 changes: 11 additions & 0 deletions src/runtime_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,14 @@ class NoSuchMember : public RuntimeError {
member.lexeme()
) } { }
};

class InvalidIntegerValue final : public RuntimeError {
public:
explicit InvalidIntegerValue(std::string_view const string)
: RuntimeError{ std::format("'{}' is not a valid integer", string) } { }
};

class DivisionByZero final : public RuntimeError {
public:
DivisionByZero() : RuntimeError{ "division by zero" } { }
};
2 changes: 1 addition & 1 deletion src/source_location.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <string_view>
#include <utility>

class Token;
struct Token;

struct SourceLocation {
std::string_view filename;
Expand Down
14 changes: 14 additions & 0 deletions src/token.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "token.hpp"
#include "runtime_error.hpp"

[[nodiscard]] std::int32_t Token::parse_integer() const {
assert(type == TokenType::IntegerLiteral);
auto stream = std::stringstream{};
stream << lexeme();
auto result = std::int32_t{};
stream >> result;
if (not stream) {
throw InvalidIntegerValue{ lexeme() };
}
return result;
}
16 changes: 5 additions & 11 deletions src/token.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,17 @@ struct Token final {
TokenType type;
SourceLocation source_location;

Token(TokenType type, SourceLocation source_location) : type{ type }, source_location{ source_location } { }
Token(TokenType const type, SourceLocation const& source_location)
: type{ type },
source_location{ source_location } { }

[[nodiscard]] std::string_view lexeme() const {
return source_location.text();
}

[[nodiscard]] std::int32_t parse_integer() const {
assert(type == TokenType::IntegerLiteral);
auto stream = std::stringstream{};
stream << lexeme();
auto result = std::int32_t{};
stream >> result;
assert(stream);
return result;
}
[[nodiscard]] std::int32_t parse_integer() const;

friend std::ostream& operator<<(std::ostream& os, Token token) {
friend std::ostream& operator<<(std::ostream& os, Token const& token) {
switch (token.type) {
default:
assert(false and "unreachable");
Expand Down
6 changes: 5 additions & 1 deletion src/values/integer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ namespace values {
if (not other->is_integer_value()) {
return BasicValue::divide(other->clone()); // throws
}
return make(value() / other->as_integer_value().value(), ValueCategory::Rvalue);
auto const rhs = other->as_integer_value().value();
if (rhs == 0) {
throw DivisionByZero{};
}
return make(value() / rhs, ValueCategory::Rvalue);
}

[[nodiscard]] Value mod(Value const& other) const override {
Expand Down

0 comments on commit 930603b

Please sign in to comment.