summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Maniero <carlos@maniero.me>2023-05-02 23:45:55 -0300
committerJohnny Richard <johnny@johnnyrichard.com>2023-05-03 22:59:03 +0200
commitd97cdd9e84879d8fc3adf4bcf5c130f498e95b79 (patch)
tree26b71c45f9ecb40be1cab4b855c155320e1538b0
parente255b793d66441097955163e3abb8f5d68ed54ba (diff)
parser: Parser allocate memory for expressions
Signed-off-by: Carlos Maniero <carlos@maniero.me>
-rw-r--r--src/parser.c107
-rw-r--r--src/parser.h4
-rw-r--r--test/parser_test.c5
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;
{