summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser.c78
-rw-r--r--src/parser.h5
-rw-r--r--src/pipac.c4
-rw-r--r--test/parser_test.c18
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, &current_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, &current_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, &current_token);
}
- if (current_token.kind != TOKEN_CCURLY) {
+ if (current_token.kind == TOKEN_EOF) {
parser_error_push_unexpected_kind(parser, &current_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];