diff options
author | Carlos Maniero <carlos@maniero.me> | 2023-05-02 23:45:55 -0300 |
---|---|---|
committer | Johnny Richard <johnny@johnnyrichard.com> | 2023-05-03 22:59:03 +0200 |
commit | d97cdd9e84879d8fc3adf4bcf5c130f498e95b79 (patch) | |
tree | 26b71c45f9ecb40be1cab4b855c155320e1538b0 | |
parent | e255b793d66441097955163e3abb8f5d68ed54ba (diff) |
parser: Parser allocate memory for expressions
Signed-off-by: Carlos Maniero <carlos@maniero.me>
-rw-r--r-- | src/parser.c | 107 | ||||
-rw-r--r-- | src/parser.h | 4 | ||||
-rw-r--r-- | test/parser_test.c | 5 |
3 files changed, 71 insertions, 45 deletions
diff --git a/src/parser.c b/src/parser.c index 2ddeb6c..516b48b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -93,14 +93,15 @@ parser_parse_type(parser_t *parser, type_t *type) return false; } -static bool -parser_literal_integer_node(ast_node_t *node, token_t *token) +static ast_node_t * +parser_literal_integer_node(token_t *token) { char number_as_str[token->value.size]; string_view_to_str(&token->value, number_as_str); + ast_node_t *node = ast_node_new(); ast_literal_integer_create(node, atoi(number_as_str)); - return true; + return node; } static ast_binary_operation_kind_t @@ -120,51 +121,62 @@ token_to_binary_operation_kind(token_t *token) } } -static bool -parser_parse_factor(parser_t *parser, ast_node_t *node) +static ast_node_t * +parser_parse_factor(parser_t *parser) { token_t token; lexer_next_token(parser->lexer, &token); switch (token.kind) { case TOKEN_NUMBER: - return parser_literal_integer_node(node, &token); - case TOKEN_OPAREN: - if (!parser_parse_expression(parser, node)) - return false; - if (!drop_expected_token(parser, TOKEN_CPAREN)) - return false; - return true; + return parser_literal_integer_node(&token); + case TOKEN_OPAREN: { + ast_node_t *expression = parser_parse_expression(parser); + + if (expression == NULL) { + return NULL; + } + + if (!drop_expected_token(parser, TOKEN_CPAREN)) { + ast_node_destroy(expression); + return NULL; + } + + return expression; + } case TOKEN_NAME: { // TODO: Check node kind, today accepts only variables ast_node_t *var_node = scope_get(parser->scope, token.value); + if (var_node == NULL) { parser_error_t error; error.token = token; sprintf(error.message, "identifier '" SVFMT "' not defined", SVARG(&token.value)); parser->errors[parser->errors_len++] = error; - return false; + return NULL; } + ast_node_t *node = ast_node_new(); ast_node_init_variable(node, &var_node->data.variable_declaration.identifier); - return true; + return node; } default: { parser_error_t error; error.token = token; sprintf(error.message, "unexpected '%s (" SVFMT ")' token", token_kind_to_str(token.kind), SVARG(&token.value)); parser->errors[parser->errors_len++] = error; - return false; + return NULL; } } } -static bool -parser_parse_term(parser_t *parser, ast_node_t *node) +static ast_node_t * +parser_parse_term(parser_t *parser) { - if (!parser_parse_factor(parser, node)) - return false; + ast_node_t *node = parser_parse_factor(parser); + if (node == NULL) + return NULL; token_t token; lexer_peek_next_token(parser->lexer, &token); @@ -172,19 +184,22 @@ parser_parse_term(parser_t *parser, ast_node_t *node) while (token.kind == TOKEN_STAR || token.kind == TOKEN_SLASH) { lexer_drop_next_token(parser->lexer); + ast_node_t *right = parser_parse_factor(parser); + + if (right == NULL) { + ast_node_destroy(node); + return NULL; + } + ast_node_t *left = ast_node_new(); *left = *node; - ast_node_t *right = ast_node_new(); - if (!parser_parse_factor(parser, right)) - return false; - ast_node_init_binary_operation(node, token_to_binary_operation_kind(&token), left, right); lexer_peek_next_token(parser->lexer, &token); } - return true; + return node; } /** @@ -194,11 +209,13 @@ parser_parse_term(parser_t *parser, ast_node_t *node) * <factor> ::= <integer> | '(' <expression> ')' * */ -bool -parser_parse_expression(parser_t *parser, ast_node_t *node) +ast_node_t * +parser_parse_expression(parser_t *parser) { - if (!parser_parse_term(parser, node)) - return false; + ast_node_t *node = parser_parse_term(parser); + + if (node == NULL) + return NULL; token_t token; lexer_peek_next_token(parser->lexer, &token); @@ -206,19 +223,22 @@ parser_parse_expression(parser_t *parser, ast_node_t *node) while (token.kind == TOKEN_PLUS || token.kind == TOKEN_MINUS) { lexer_drop_next_token(parser->lexer); + ast_node_t *right = parser_parse_term(parser); + + if (right == NULL) { + ast_node_destroy(node); + return NULL; + } + ast_node_t *left = ast_node_new(); *left = *node; - ast_node_t *right = ast_node_new(); - if (!parser_parse_term(parser, right)) - return false; - ast_node_init_binary_operation(node, token_to_binary_operation_kind(&token), left, right); lexer_peek_next_token(parser->lexer, &token); } - return true; + return node; } static ast_node_t * @@ -228,9 +248,8 @@ parser_parse_return_stmt(parser_t *parser) return NULL; } - ast_node_t *argument_token = ast_node_new(); - if (!parser_parse_expression(parser, argument_token)) { - ast_node_destroy(argument_token); + ast_node_t *argument_token = parser_parse_expression(parser); + if (argument_token == NULL) { return NULL; } @@ -256,9 +275,13 @@ parser_parse_variable_assignment(parser_t *parser) if (!drop_expected_token(parser, TOKEN_EQUAL)) return NULL; - ast_node_t *expression = ast_node_new(); + ast_node_t *expression = parser_parse_expression(parser); + + if (expression == NULL) { + return NULL; + } - if (!parser_parse_expression(parser, expression) || !drop_expected_token(parser, TOKEN_SEMICOLON)) { + if (!drop_expected_token(parser, TOKEN_SEMICOLON)) { ast_node_destroy(expression); return NULL; } @@ -304,9 +327,13 @@ parser_parse_variable_definition(parser_t *parser) return NULL; } - ast_node_t *expression = ast_node_new(); + ast_node_t *expression = parser_parse_expression(parser); - if (!parser_parse_expression(parser, expression) || !drop_expected_token(parser, TOKEN_SEMICOLON)) { + if (expression == NULL) { + return NULL; + } + + if (!drop_expected_token(parser, TOKEN_SEMICOLON)) { ast_node_destroy(expression); return NULL; } diff --git a/src/parser.h b/src/parser.h index 27feb17..ef5dff5 100644 --- a/src/parser.h +++ b/src/parser.h @@ -43,7 +43,7 @@ parser_init(parser_t *parser, lexer_t *lexer, scope_t *scope); ast_node_t * parser_parse_function_declaration(parser_t *parser); -bool -parser_parse_expression(parser_t *parser, ast_node_t *node); +ast_node_t * +parser_parse_expression(parser_t *parser); #endif /* PARSER_H */ diff --git a/test/parser_test.c b/test/parser_test.c index ce77828..2d749da 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -140,9 +140,8 @@ test_parse_arithmetic_expression(const MunitParameter params[], void *user_data_ make_lexer_from_static_src(&lexer, "1 + 3 * 3 / 2 - 1"); parser_init(&parser, &lexer, scope); - ast_node_t *ast_expression = ast_node_new(); - bool parsed = parser_parse_expression(&parser, ast_expression); - assert_true(parsed); + ast_node_t *ast_expression = parser_parse_expression(&parser); + assert_not_null(ast_expression); ast_node_t *exp1 = ast_expression; { |