extracted to a function the casting of the
different types to make tests cleaner
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include "ast/expressions/identifier.hpp"
|
#include "ast/expressions/identifier.hpp"
|
||||||
#include "ast/expressions/integer.hpp"
|
#include "ast/expressions/integer.hpp"
|
||||||
|
#include "ast/expressions/prefix.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
@@ -11,24 +12,11 @@ TEST_SUITE("Parser: expression") {
|
|||||||
) {
|
) {
|
||||||
setup("foobar;");
|
setup("foobar;");
|
||||||
REQUIRE(program->statements.size() == 1);
|
REQUIRE(program->statements.size() == 1);
|
||||||
ast::expression_stmt* expression_stmt;
|
ast::expression_stmt* expression_stmt =
|
||||||
REQUIRE_NOTHROW(
|
cast<ast::expression_stmt>(program->statements[0]);
|
||||||
expression_stmt =
|
|
||||||
dynamic_cast<ast::expression_stmt*>(program->statements[0])
|
|
||||||
);
|
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
expression_stmt != nullptr,
|
|
||||||
"Couldn't cast statement to an expression statement"
|
|
||||||
);
|
|
||||||
|
|
||||||
ast::identifier* ident;
|
ast::identifier* ident =
|
||||||
REQUIRE_NOTHROW(
|
cast<ast::identifier>(expression_stmt->expression);
|
||||||
ident = dynamic_cast<ast::identifier*>(expression_stmt->expression)
|
|
||||||
);
|
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
ident != nullptr,
|
|
||||||
"Couldn't cast expression to an identifier"
|
|
||||||
);
|
|
||||||
|
|
||||||
REQUIRE(ident->value == "foobar");
|
REQUIRE(ident->value == "foobar");
|
||||||
REQUIRE(ident->token_literal() == "foobar");
|
REQUIRE(ident->token_literal() == "foobar");
|
||||||
@@ -40,27 +28,61 @@ TEST_SUITE("Parser: expression") {
|
|||||||
) {
|
) {
|
||||||
setup("5;");
|
setup("5;");
|
||||||
REQUIRE(program->statements.size() == 1);
|
REQUIRE(program->statements.size() == 1);
|
||||||
ast::expression_stmt* expression_stmt;
|
|
||||||
REQUIRE_NOTHROW(
|
|
||||||
expression_stmt =
|
|
||||||
dynamic_cast<ast::expression_stmt*>(program->statements[0])
|
|
||||||
);
|
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
expression_stmt != nullptr,
|
|
||||||
"Couldn't cast statement to an expression statement"
|
|
||||||
);
|
|
||||||
|
|
||||||
ast::integer_literal* int_lit;
|
ast::expression_stmt* expression_stmt =
|
||||||
REQUIRE_NOTHROW(
|
cast<ast::expression_stmt>(program->statements[0]);
|
||||||
int_lit =
|
|
||||||
dynamic_cast<ast::integer_literal*>(expression_stmt->expression)
|
ast::integer_literal* int_lit =
|
||||||
);
|
cast<ast::integer_literal>(expression_stmt->expression);
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
int_lit != nullptr,
|
|
||||||
"Couldn't cast expression to an identifier"
|
|
||||||
);
|
|
||||||
|
|
||||||
REQUIRE(int_lit->value == 5);
|
REQUIRE(int_lit->value == 5);
|
||||||
REQUIRE(int_lit->token_literal() == "5");
|
REQUIRE(int_lit->token_literal() == "5");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TEST_CASE_FIXTURE(
|
||||||
|
// ParserFixture,
|
||||||
|
// "Simple expression statement with prefix before integer"
|
||||||
|
// ) {
|
||||||
|
// SUBCASE("Prefix: '!'") {
|
||||||
|
// setup("!5;");
|
||||||
|
//
|
||||||
|
// REQUIRE(program->statements.size() == 1);
|
||||||
|
// ast::expression_stmt* expression_stmt =
|
||||||
|
// cast<ast::expression_stmt>(program->statements[0]);
|
||||||
|
//
|
||||||
|
// ast::prefix_expr* prefix_expr;
|
||||||
|
// REQUIRE_NOTHROW(
|
||||||
|
// prefix_expr =
|
||||||
|
// dynamic_cast<ast::prefix_expr*>(expression_stmt->expression)
|
||||||
|
// );
|
||||||
|
// REQUIRE_MESSAGE(
|
||||||
|
// prefix_expr != nullptr,
|
||||||
|
// "Couldn't cast expression to an identifier"
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// REQUIRE(prefix_expr->value == 5);
|
||||||
|
// REQUIRE(prefix_expr->token_literal() == "5");
|
||||||
|
// }
|
||||||
|
// SUBCASE("Prefix: '-'") {
|
||||||
|
// setup("-15;");
|
||||||
|
//
|
||||||
|
// REQUIRE(program->statements.size() == 1);
|
||||||
|
// ast::expression_stmt* expression_stmt =
|
||||||
|
// get_expression_stmt(program->statements[0]);
|
||||||
|
//
|
||||||
|
// ast::integer_literal* int_lit;
|
||||||
|
// REQUIRE_NOTHROW(
|
||||||
|
// int_lit = dynamic_cast<ast::integer_literal*>(
|
||||||
|
// expression_stmt->expression
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
// REQUIRE_MESSAGE(
|
||||||
|
// int_lit != nullptr,
|
||||||
|
// "Couldn't cast expression to an identifier"
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// REQUIRE(int_lit->value == 5);
|
||||||
|
// REQUIRE(int_lit->token_literal() == "5");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "ast/statements/let.hpp"
|
#include "ast/statements/let.hpp"
|
||||||
|
|
||||||
#include "ast/ast.hpp"
|
#include "ast/ast.hpp"
|
||||||
|
#include "ast/errors/error.hpp"
|
||||||
#include "lexer/lexer.hpp"
|
#include "lexer/lexer.hpp"
|
||||||
#include "parser/parser.hpp"
|
#include "parser/parser.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
@@ -10,12 +11,7 @@
|
|||||||
|
|
||||||
void test_let_statement(ast::statement* stmt, const std::string name) {
|
void test_let_statement(ast::statement* stmt, const std::string name) {
|
||||||
REQUIRE(stmt->token_literal() == "let");
|
REQUIRE(stmt->token_literal() == "let");
|
||||||
ast::let_stmt* let_stmt;
|
ast::let_stmt* let_stmt = cast<ast::let_stmt>(stmt);
|
||||||
REQUIRE_NOTHROW(let_stmt = dynamic_cast<ast::let_stmt*>(stmt));
|
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
let_stmt != nullptr,
|
|
||||||
"Couldn't cast statement to a let statement"
|
|
||||||
);
|
|
||||||
|
|
||||||
REQUIRE(let_stmt->name->value == name);
|
REQUIRE(let_stmt->name->value == name);
|
||||||
REQUIRE(let_stmt->name->token_literal() == name);
|
REQUIRE(let_stmt->name->token_literal() == name);
|
||||||
@@ -38,13 +34,8 @@ void test_failing_let_parsing(
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto& e : p.errors) {
|
for (auto& e : p.errors) {
|
||||||
ast::error::expected_next* en;
|
ast::error::expected_next* en = cast<ast::error::expected_next>(e);
|
||||||
|
|
||||||
REQUIRE_NOTHROW(en = dynamic_cast<ast::error::expected_next*>(e));
|
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
en != nullptr,
|
|
||||||
"Couldn't cast the error to an 'expected_next'"
|
|
||||||
);
|
|
||||||
REQUIRE(en->expected_type == expected_types[i++]);
|
REQUIRE(en->expected_type == expected_types[i++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,12 +14,7 @@ return 103213;\
|
|||||||
|
|
||||||
for (const auto stmt : program->statements) {
|
for (const auto stmt : program->statements) {
|
||||||
REQUIRE(stmt->token_literal() == "return");
|
REQUIRE(stmt->token_literal() == "return");
|
||||||
ast::return_stmt* let_stmt;
|
ast::return_stmt* return_stmt = cast<ast::return_stmt>(stmt);
|
||||||
REQUIRE_NOTHROW(let_stmt = dynamic_cast<ast::return_stmt*>(stmt));
|
|
||||||
REQUIRE_MESSAGE(
|
|
||||||
let_stmt != nullptr,
|
|
||||||
"Couldn't cast statement to a return statement"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,45 @@
|
|||||||
|
#include "ast/ast.hpp"
|
||||||
#include "lexer/lexer.hpp"
|
#include "lexer/lexer.hpp"
|
||||||
#include "parser/parser.hpp"
|
#include "parser/parser.hpp"
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
void check_parser_errors(const std::vector<ast::error::error*>& errors);
|
void check_parser_errors(const std::vector<ast::error::error*>&);
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <typename T, typename Base>
|
||||||
|
T* cast_impl(Base* base) {
|
||||||
|
static_assert(
|
||||||
|
std::is_base_of_v<Base, T>,
|
||||||
|
"T must be derived from Base"
|
||||||
|
);
|
||||||
|
|
||||||
|
T* t;
|
||||||
|
REQUIRE_NOTHROW(t = dynamic_cast<T*>(base));
|
||||||
|
REQUIRE_MESSAGE(
|
||||||
|
t != nullptr,
|
||||||
|
"Couldn't cast expression to a " * std::string(typeid(T).name())
|
||||||
|
);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Overloads for your known base types
|
||||||
|
template <typename T>
|
||||||
|
T* cast(ast::expression* expr) {
|
||||||
|
return cast_impl<T, ast::expression>(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* cast(ast::statement* stmt) {
|
||||||
|
return cast_impl<T, ast::statement>(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* cast(ast::error::error* err) {
|
||||||
|
return cast_impl<T, ast::error::error>(err);
|
||||||
|
}
|
||||||
|
|
||||||
struct ParserFixture {
|
struct ParserFixture {
|
||||||
std::stringstream input;
|
std::stringstream input;
|
||||||
|
Reference in New Issue
Block a user