Skip to content

Commit

Permalink
🐛 Handle unrecognized tokens.
Browse files Browse the repository at this point in the history
Also add unit tests to cover this.
  • Loading branch information
karnkaul committed Oct 8, 2023
1 parent 29f781e commit e651a2b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 1 deletion.
7 changes: 7 additions & 0 deletions kalcy/include/kalcy/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ struct InternalError : Error {
using Error::Error;
};

///
/// \brief Unrecognized token.
///
struct UnrecognizedToken : Error {
explicit UnrecognizedToken(Token token);
};

///
/// \brief Parse error.
///
Expand Down
2 changes: 2 additions & 0 deletions kalcy/src/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ auto Error::build_highlight(char const higlight) const -> std::string {
return ret.str();
}

UnrecognizedToken::UnrecognizedToken(Token const token) : Error(token, std::format("unrecognized token: '{}'", token.lexeme)) {}

ParseError::ParseError(Token const token) : Error(token, "parse error") {}

ParseError::ParseError(Token const token, Token::Type const expected)
Expand Down
3 changes: 2 additions & 1 deletion kalcy/src/scanner.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <kalcy/error.hpp>
#include <kalcy/scanner.hpp>
#include <cassert>
#include <cctype>
Expand Down Expand Up @@ -28,7 +29,7 @@ auto Scanner::next() -> Token {
if (match_number(out)) { return out; }
if (match_identifier(out)) { return out; }

return {};
throw UnrecognizedToken{make_token(Token::Type::eNone, {&m_text.front(), 1})};
}

auto Scanner::match_single(Token& out) -> bool {
Expand Down
22 changes: 22 additions & 0 deletions tests/tests/test_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,28 @@ ADD_TEST(ParseErrorOnExtraneous) {
EXPECT(did_throw);
}

ADD_TEST(ParseErrorOnInvalidToken) {
bool did_throw{};
try {
parse("`");
} catch (UnrecognizedToken const& e) {
EXPECT(e.token.location == 0);
EXPECT(e.token.lexeme == "`");
did_throw = true;
}
EXPECT(did_throw);

did_throw = false;
try {
parse("pi@");
} catch (UnrecognizedToken const& e) {
EXPECT(e.token.location == 2);
EXPECT(e.token.lexeme == "@");
did_throw = true;
}
EXPECT(did_throw);
}

ADD_TEST(ParsePrecedence) {
auto result = parse("1 + 2 * 3");
ASSERT(result != nullptr);
Expand Down

0 comments on commit e651a2b

Please sign in to comment.