From 77dbf3a5011566b4a6274b3cdfa075dd723642d3 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Tue, 2 May 2023 23:45:49 -0300 Subject: Parser: Make the parser function return the ast_node In many situations, the parser is responsible for reserving memory for nodes, particularly during function body parsing. This commit introduces a new standard where parser functions not only allocate memory for ast_nodes, but also return them. In case of a parser error, a NULL pointer is returned. This standard will be extended to other parsers in future commits, ensuring consistency throughout the codebase. Signed-off-by: Carlos Maniero --- src/parser.c | 78 ++++++++++++++++++++++++++++++++++-------------------- src/parser.h | 5 ++-- src/pipac.c | 4 +-- test/parser_test.c | 18 +++++-------- 4 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/parser.c b/src/parser.c index ad0fdc9..ca5600d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -296,19 +296,26 @@ parser_parse_variable_definition(parser_t *parser, string_view_t variable_name, return true; } -static bool -parser_parse_block_declarations(parser_t *parser, vector_t *body) +static vector_t * +parser_parse_block_declarations(parser_t *parser) { + if (!drop_expected_token(parser, TOKEN_OCURLY)) { + return NULL; + } + token_t current_token; lexer_next_token(parser->lexer, ¤t_token); scope_enter(parser->scope); + vector_t *body = vector_new(); + while (current_token.kind != TOKEN_CCURLY && current_token.kind != TOKEN_EOF) { if (current_token.kind != TOKEN_NAME) { parser_error_push_unexpected_kind(parser, ¤t_token, TOKEN_NAME); scope_leave(parser->scope); - return false; + vector_destroy(body); + return NULL; } if (string_view_eq(current_token.value, string_view_from_str("return"))) { @@ -318,7 +325,8 @@ parser_parse_block_declarations(parser_t *parser, vector_t *body) if (!parsed_return) { ast_node_destroy(return_node); scope_leave(parser->scope); - return false; + vector_destroy(body); + return NULL; } vector_push_back(body, return_node); @@ -332,7 +340,8 @@ parser_parse_block_declarations(parser_t *parser, vector_t *body) if (!parser_parse_variable_definition(parser, current_token.value, variable_node)) { ast_node_destroy(variable_node); - return false; + vector_destroy(body); + return NULL; } vector_push_back(body, variable_node); @@ -343,7 +352,8 @@ parser_parse_block_declarations(parser_t *parser, vector_t *body) if (!parser_parse_variable_assignment(parser, current_token, variable_assignment)) { ast_node_destroy(variable_assignment); - return false; + vector_destroy(body); + return NULL; } vector_push_back(body, variable_assignment); @@ -369,10 +379,11 @@ parser_parse_block_declarations(parser_t *parser, vector_t *body) lexer_next_token(parser->lexer, ¤t_token); } - if (current_token.kind != TOKEN_CCURLY) { + if (current_token.kind == TOKEN_EOF) { parser_error_push_unexpected_kind(parser, ¤t_token, TOKEN_CCURLY); scope_leave(parser->scope); - return false; + vector_destroy(body); + return NULL; } ast_node_t *latest_node = vector_at(body, body->size - 1); @@ -385,44 +396,55 @@ parser_parse_block_declarations(parser_t *parser, vector_t *body) parser->errors[parser->errors_len++] = error; scope_leave(parser->scope); - return false; + vector_destroy(body); + return NULL; } + scope_leave(parser->scope); - return true; + return body; } -bool -parser_parse_function_declaration(parser_t *parser, ast_node_t *node) +static bool +parser_parse_function_arguments(parser_t *parser) +{ + return drop_expected_token(parser, TOKEN_OPAREN) && drop_expected_token(parser, TOKEN_CPAREN); +} + +ast_node_t * +parser_parse_function_declaration(parser_t *parser) { token_t func_name_token; if (!expected_token(&func_name_token, parser, TOKEN_NAME)) { - return false; + return NULL; } - if (!drop_expected_token(parser, TOKEN_OPAREN)) - return false; - if (!drop_expected_token(parser, TOKEN_CPAREN)) - return false; - if (!drop_expected_token(parser, TOKEN_COLON)) - return false; + if (!parser_parse_function_arguments(parser)) { + return NULL; + } + + if (!drop_expected_token(parser, TOKEN_COLON)) { + return NULL; + } type_t return_type; if (!parser_parse_type(parser, &return_type)) { - return false; + return NULL; } - if (!drop_expected_token(parser, TOKEN_OCURLY)) - return false; + vector_t *body = parser_parse_block_declarations(parser); - vector_t *body = vector_new(); + if (body == NULL) { + return NULL; + } + + ast_node_t *node = ast_node_new(); ast_node_init_function_declaration(node, func_name_token.value, return_type, body); - scope_push(parser->scope, &node->data.function.identifier, node); - if (!parser_parse_block_declarations(parser, body)) { - return false; - } + // TODO: When implementing function calls the scope must be pushed before the + // body to be parsed, otherwise recursion not gonna work. + scope_push(parser->scope, &node->data.function.identifier, node); - return true; + return node; } diff --git a/src/parser.h b/src/parser.h index d3e1431..27feb17 100644 --- a/src/parser.h +++ b/src/parser.h @@ -40,8 +40,9 @@ typedef struct parser_t void parser_init(parser_t *parser, lexer_t *lexer, scope_t *scope); -bool -parser_parse_function_declaration(parser_t *parser, ast_node_t *node); +ast_node_t * +parser_parse_function_declaration(parser_t *parser); + bool parser_parse_expression(parser_t *parser, ast_node_t *node); diff --git a/src/pipac.c b/src/pipac.c index 2041218..e3caec1 100644 --- a/src/pipac.c +++ b/src/pipac.c @@ -67,9 +67,9 @@ main(int argc, char **argv) parser_t parser; parser_init(&parser, &lexer, scope); - ast_node_t *func = ast_node_new(); + ast_node_t *func = parser_parse_function_declaration(&parser); - if (!parser_parse_function_declaration(&parser, func)) { + if (func == NULL) { parser_print_errors(&parser); return EXIT_FAILURE; } diff --git a/test/parser_test.c b/test/parser_test.c index 8f75e07..f923c46 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -48,14 +48,12 @@ assert_parser_error(char *src, char *error_msg) make_lexer_from_static_src(&lexer, src); parser_init(&parser, &lexer, scope); - ast_node_t *ast_function = ast_node_new(); + ast_node_t *ast_function = parser_parse_function_declaration(&parser); - bool parsed = parser_parse_function_declaration(&parser, ast_function); - assert_false(parsed); + assert_false(ast_function != NULL); assert_int(1, ==, parser.errors_len); assert_string_equal(error_msg, parser.errors[0].message); - ast_node_destroy(ast_function); scope_destroy(scope); } @@ -68,10 +66,8 @@ test_parse_function(const MunitParameter params[], void *user_data_or_fixture) make_lexer_from_static_src(&lexer, "main(): i32 { \nreturn 42;\n }"); parser_init(&parser, &lexer, scope); - ast_node_t *ast_function = ast_node_new(); - - bool parsed = parser_parse_function_declaration(&parser, ast_function); - assert_true(parsed); + ast_node_t *ast_function = parser_parse_function_declaration(&parser); + assert_true(ast_function != NULL); char actual[5]; @@ -103,11 +99,9 @@ test_parse_variable_definition(const MunitParameter params[], void *user_data_or make_lexer_from_static_src(&lexer, "main(): i32 { \nvariable : i32 = 42; \nreturn variable;\n }"); parser_init(&parser, &lexer, scope); - ast_node_t *ast_function = ast_node_new(); + ast_node_t *ast_function = parser_parse_function_declaration(&parser); - bool parsed = parser_parse_function_declaration(&parser, ast_function); - - assert_true(parsed); + assert_true(ast_function != NULL); char actual[5]; -- cgit v1.2.3