From cbafb2e814698a819d58e767c3d3e79a99c11d22 Mon Sep 17 00:00:00 2001 From: Karma Riuk Date: Mon, 14 Jul 2025 20:15:51 +0200 Subject: [PATCH] extracted and abstracted function --- test/parser/let.cpp | 42 ++++-------------------------------------- test/parser/utils.cpp | 38 ++++++++++++++++++++++++++++++++++++++ test/parser/utils.hpp | 1 + 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/test/parser/let.cpp b/test/parser/let.cpp index a1e19ae..9cfb624 100644 --- a/test/parser/let.cpp +++ b/test/parser/let.cpp @@ -1,14 +1,10 @@ #include "ast/statements/let.hpp" #include "ast/ast.hpp" -#include "ast/errors/error.hpp" -#include "lexer/lexer.hpp" -#include "parser/parser.hpp" #include "utils.hpp" #include #include -#include void test_let_statement(ast::statement* stmt, const std::string name) { REQUIRE(stmt->token_literal() == "let"); @@ -18,52 +14,22 @@ void test_let_statement(ast::statement* stmt, const std::string name) { REQUIRE(let_stmt->name->token_literal() == name); } -void test_failing_let_parsing( - std::string input_s, - std::vector expected_types, - int n_good_statements = 0 -) { - std::stringstream input(input_s); - - lexer::lexer l{input}; - parser::parser p{l}; - - std::unique_ptr program = p.parse_program(); - - // Check for errors - REQUIRE(p.errors.size() == expected_types.size()); - - int i = 0; - for (auto& e : p.errors) { - ast::error::expected_next* en = cast(e); - - REQUIRE(en->expected_type == expected_types[i++]); - } - - // normal program check - REQUIRE_MESSAGE( - program != nullptr, - "parse_program() returned a null pointer" - ); - REQUIRE(program->statements.size() == n_good_statements); -} - TEST_SUITE("Parser: let") { TEST_CASE("Malformed let statement (checking for memory leaks)") { SUBCASE("Second token not identifier") { - test_failing_let_parsing("let 5 = 5;", {token::type::IDENTIFIER}); + test_failing_parsing("let 5 = 5;", {token::type::IDENTIFIER}); } SUBCASE("Third token not '='") { - test_failing_let_parsing("let five ! 5;", {token::type::ASSIGN}); + test_failing_parsing("let five ! 5;", {token::type::ASSIGN}); } SUBCASE("Missing both identifier and '='") { - test_failing_let_parsing("let 5;", {token::type::IDENTIFIER}); + test_failing_parsing("let 5;", {token::type::IDENTIFIER}); } SUBCASE("Multiple parsing errors") { - test_failing_let_parsing( + test_failing_parsing( "let 5; let ! = 5; let five = 5; let five 5; let;", {token::type::IDENTIFIER, token::type::IDENTIFIER, diff --git a/test/parser/utils.cpp b/test/parser/utils.cpp index 7cad464..e688ab7 100644 --- a/test/parser/utils.cpp +++ b/test/parser/utils.cpp @@ -87,3 +87,41 @@ void test_infix_expression( CHECK(op_exp->op == op); test_literal_expression(op_exp->right, right); } + +void test_failing_parsing( + std::string input_s, + std::vector expected_types, + int n_good_statements +) { + std::stringstream input(input_s); + + lexer::lexer l{input}; + parser::parser p{l}; + + std::unique_ptr program = p.parse_program(); + + // Check for errors + REQUIRE(p.errors.size() >= expected_types.size()); + // ^^ because even though you were thinking + // about a specific token to be there, other `expect_next -> false` might be + // triggered for subexpressions due to the first one + + int i = 0; + for (auto& t : expected_types) { + ast::error::expected_next* en = + cast(p.errors[i++]); + + REQUIRE(en->expected_type == t); + } + + // normal program check + REQUIRE_MESSAGE( + program != nullptr, + "parse_program() returned a null pointer" + ); + REQUIRE(program->statements.size() >= n_good_statements); + // ^^ because even though you were thinking + // about a specific number of statements to be there, it failing for + // `expect_next` might trigger a sub-expression to be triggered correctly + // and be parsed as the expression_stmt +} diff --git a/test/parser/utils.hpp b/test/parser/utils.hpp index 7318cba..8cad691 100644 --- a/test/parser/utils.hpp +++ b/test/parser/utils.hpp @@ -67,3 +67,4 @@ void test_integer_literal(ast::expression*, int); void test_boolean_literal(ast::expression*, bool); void test_literal_expression(ast::expression*, std::any&); void test_infix_expression(ast::expression*, std::any, std::string, std::any); +void test_failing_parsing(std::string, std::vector, int = 0);