diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/src/parser.c b/src/parser.c index 377ff73..fe2a2f0 100644 --- a/src/parser.c +++ b/src/parser.c @@ -33,6 +33,9 @@ parser_expression_matches_the_expected_type(parser_t *parser, ast_node_t *expres static ast_node_t * parser_parse_block_declarations(parser_t *parser, type_t result_type); +static bool +is_next_token_cparen(parser_t *parser); + void parser_init(parser_t *parser, lexer_t *lexer, scope_t *scope) { @@ -354,16 +357,40 @@ parser_parse_factor(parser_t *parser) referenced_node->data.variable_declaration.type); } + // Function parameters are also variables. + if (referenced_node->kind == AST_FUNCTION_PARAMETER) { + return ast_node_new_variable(&referenced_node->data.function_parameter.identifier, + referenced_node->data.function_parameter.type); + } + // Parse function parameters if (!drop_expected_token(parser, TOKEN_OPAREN)) { return NULL; } - if (!drop_expected_token(parser, TOKEN_CPAREN)) { - return NULL; + + vector_t *arguments = vector_new(); + + while (!is_next_token_cparen(parser)) { + ast_node_t *argument = parser_parse_expression(parser); + + if (argument == NULL) { + ast_node_destroy_vector(arguments); + return NULL; + } + + vector_push_back(arguments, argument); + + if (!is_next_token_cparen(parser) && !drop_expected_token(parser, TOKEN_COMMA)) { + ast_node_destroy_vector(arguments); + return NULL; + } } - return ast_node_new_function_call(&referenced_node->data.function.identifier, - referenced_node->data.function.return_type); + drop_expected_token(parser, TOKEN_CPAREN); + + return ast_node_new_function_call(ast_node_function_declaration_identifier(referenced_node), + referenced_node->data.function.prototype.return_type, + arguments); } default: { parser_error_t error; @@ -591,6 +618,14 @@ is_next_function_declaration(parser_t *parser) } static bool +is_next_token_cparen(parser_t *parser) +{ + token_t token; + lexer_peek_next_token(parser->lexer, &token); + return token.kind == TOKEN_CPAREN; +} + +static bool is_next_token_eof(parser_t *parser) { token_t token; @@ -722,10 +757,48 @@ parser_parse_block_declarations(parser_t *parser, type_t result_type) return ast_node_new_block(body); } -static bool -parser_parse_function_arguments(parser_t *parser) +static vector_t * +parser_parse_function_parameters(parser_t *parser) { - return drop_expected_token(parser, TOKEN_OPAREN) && drop_expected_token(parser, TOKEN_CPAREN); + if (!drop_expected_token(parser, TOKEN_OPAREN)) { + return NULL; + } + + vector_t *vector = vector_new(); + + while (!is_next_token_cparen(parser)) { + token_t token_name; + type_t type; + + if (!expected_token(&token_name, parser, TOKEN_NAME)) { + ast_node_destroy_vector(vector); + return NULL; + } + if (!drop_expected_token(parser, TOKEN_COLON)) { + ast_node_destroy_vector(vector); + return NULL; + } + + if (!parser_parse_type(parser, &type)) { + ast_node_destroy_vector(vector); + return NULL; + } + + ast_node_t *parameter = ast_node_new_function_parameter(token_name.value, type); + + scope_push(parser->scope, ¶meter->data.function_parameter.identifier, parameter); + + vector_push_back(vector, parameter); + + if (!is_next_token_cparen(parser) && !drop_expected_token(parser, TOKEN_COMMA)) { + ast_node_destroy_vector(vector); + return NULL; + } + } + + drop_expected_token(parser, TOKEN_CPAREN); + + return vector; } ast_node_t * @@ -741,7 +814,9 @@ parser_parse_function_declaration(parser_t *parser) return NULL; } - if (!parser_parse_function_arguments(parser)) { + vector_t *parameters = parser_parse_function_parameters(parser); + + if (parameters == NULL) { return NULL; } @@ -766,11 +841,11 @@ parser_parse_function_declaration(parser_t *parser) return NULL; } - ast_node_t *node = ast_node_new_function_declaration(func_name_token.value, return_type, body); + ast_node_t *node = ast_node_new_function_declaration(func_name_token.value, return_type, parameters, body); // 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); + scope_push(parser->scope, &node->data.function.prototype.identifier, node); return node; } |