From c1a1bd2320b4c1508c4ab20d23b7c193a94d8026 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Tue, 25 Apr 2023 03:52:59 -0300 Subject: parser: Add support for variables and identifiers in function body This commit adds support for variables and identifiers in the function body of the parser, stored as a vector. However, at this point, identifier resolution is not fully implemented, and we currently accept identifiers without checking if they can be resolved. This is a known limitation that will be addressed in a future commit once hash-tables are added to the parser. Signed-off-by: Carlos Maniero Reviewed-by: Johnny Richard --- test/parser_test.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) (limited to 'test/parser_test.c') diff --git a/test/parser_test.c b/test/parser_test.c index 2e73fa6..daa2fe7 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -15,11 +15,12 @@ * along with this program. If not, see . */ #define MUNIT_ENABLE_ASSERT_ALIASES -#include "munit.h" +#include "ast.h" #include "lexer.h" +#include "munit.h" #include "parser.h" -#include "ast.h" #include "string.h" +#include "vector.h" void assert_string_view_equal(char *expected, string_view_t actual); @@ -49,6 +50,8 @@ assert_parser_error(char* src, char* error_msg) { assert_false(parsed); assert_int(1, ==, parser.errors_len); assert_string_equal(error_msg, parser.errors[0].message); + + ast_node_destroy(ast_function); } static MunitResult @@ -71,7 +74,7 @@ test_parse_function(const MunitParameter params[], assert_string_equal("main", actual); assert_int(AST_FUNCTION_DECLARATION, ==, ast_function->kind); - ast_node_t *ast_return = ast_function->data.function.body; + ast_node_t *ast_return = vector_at(ast_function->data.function.body, 0); assert_int(AST_RETURN_STMT, ==, ast_return->kind); @@ -85,6 +88,46 @@ test_parse_function(const MunitParameter params[], return MUNIT_OK; } +static MunitResult +test_parse_variable_definition(const MunitParameter params[], + void *user_data_or_fixture) +{ + parser_t parser; + lexer_t lexer; + + make_lexer_from_static_src(&lexer, "main(): i32 { \nvariable : i32 = 42; \nreturn variable;\n }"); + parser_init(&parser, &lexer); + ast_node_t *ast_function = ast_node_new(); + + bool parsed = parser_parse_function_declaration(&parser, ast_function); + + assert_true(parsed); + + char actual[5]; + + string_view_to_str(&ast_function->data.function.name, actual); + assert_string_equal("main", actual); + assert_int(AST_FUNCTION_DECLARATION, ==, ast_function->kind); + + ast_node_t *ast_variable = vector_at(ast_function->data.function.body, 0); + + assert_int(AST_VARIABLE_DECLARATION, ==, ast_variable->kind); + assert_string_view_equal("variable", ast_variable->data.variable.name); + + ast_node_t *ast_return = vector_at(ast_function->data.function.body, 1); + + assert_int(AST_RETURN_STMT, ==, ast_return->kind); + + ast_node_t *ast_literal = ast_return->data.return_stmt.argument; + + assert_int(AST_IDENTIFIER, ==, ast_literal->kind); + assert_string_view_equal("variable", ast_literal->data.identifier.name); + + ast_node_destroy(ast_function); + + return MUNIT_OK; +} + static MunitResult test_parse_arithmetic_expression(const MunitParameter params[], void *user_data_or_fixture) @@ -167,15 +210,20 @@ test_parse_basic_syntax_errors(const MunitParameter params[], assert_parser_error("main(): i32 { return; }" , "unexpected '; (;)' token"); assert_parser_error("main(): i32 { return 42;" , "expected '}' but got end of file"); assert_parser_error("main(): beff { return 42; }" , "type 'beff' is not defined"); - assert_parser_error("main(): i32 { oxi 42; }" , "expected 'return' keyword but got 'oxi'"); + // FIXME: once function calls are implemented, this error should inform that + // neither a variable or function call was found. + assert_parser_error("main(): i32 { oxi 42; }" , "expected ':' but got 'TOKEN_NUMBER'"); return MUNIT_OK; } static MunitTest tests[] = { + { "/test_parse_function", test_parse_function, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, { "/test_parse_function", test_parse_function, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, { "/test_parse_basic_syntax_errors", test_parse_basic_syntax_errors, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, { "/test_parse_arithmetic_expression", test_parse_arithmetic_expression, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, + { "/test_parse_arithmetic_expression", test_parse_arithmetic_expression, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, + { "/test_parse_variable_definition", test_parse_variable_definition, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } }; -- cgit v1.2.3