From 132f4f3a539c012f4345d8c5a97947c524be3ba0 Mon Sep 17 00:00:00 2001 From: matteo Date: Sat, 31 Jan 2026 13:24:44 +0100 Subject: [PATCH] feat(parser + ast): function parsing support --- src/parser/grammar_advanced.c | 51 ++++++++++++++++++++++++++++++++--- src/parser/grammar_advanced.h | 2 +- src/parser/grammar_basic.c | 1 - src/utils/ast/ast_function.c | 2 +- src/utils/ast/ast_function.h | 9 ++++--- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/parser/grammar_advanced.c b/src/parser/grammar_advanced.c index 22e3b9b..9968ba6 100644 --- a/src/parser/grammar_advanced.c +++ b/src/parser/grammar_advanced.c @@ -149,12 +149,55 @@ struct ast *parse_prefix(struct lexer_context *ctx) } } -// TODO NOT IMPLEMENTED struct ast *parse_funcdec(struct lexer_context *ctx) { - (void)ctx; - perror("Error: usage of a not implemented function (parse_funcdec)"); - return NULL; + struct token *token = PEEK_TOKEN(); + struct ast *value = NULL; + char *func_name = NULL; + + if (token->type != TOKEN_WORD) + { + return NULL; + } + + // word -> func name + POP_TOKEN(); + func_name = strdup(token->data); + + // ( + token = PEEK_TOKEN(); + if (token->type != TOKEN_LEFT_PAREN) + { + free(func_name); + return NULL; + } + POP_TOKEN(); + + // ) + token = PEEK_TOKEN(); + if (token->type != TOKEN_RIGHT_PAREN) + { + free(func_name); + return NULL; + } + POP_TOKEN(); + token = PEEK_TOKEN(); + + // { \n } + while (token->type == TOKEN_NEWLINE) + { + POP_TOKEN(); + token = PEEK_TOKEN(); + } + + // shell_command -> value + value = parse_shell_command(ctx); + if (value == NULL) + { + free(name); + return NULL; + } + return ast_create_function(name, value); } struct ast *parse_for(struct lexer_context *ctx) diff --git a/src/parser/grammar_advanced.h b/src/parser/grammar_advanced.h index 2b9cc63..1b074ad 100644 --- a/src/parser/grammar_advanced.h +++ b/src/parser/grammar_advanced.h @@ -26,7 +26,7 @@ struct ast *parse_prefix(struct lexer_context *ctx); /* * @brief parses a funcdec rule - * @warning NOT IMPLEMENTED + * @warning Work in progress * * @code funcdec = WORD '(' ')' {'\n'} shell_command ; * diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index df103fc..d86abb6 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -223,7 +223,6 @@ struct ast *parse_command(struct lexer_context *ctx) { result = parse_shell_command(ctx); } - // WARNING funcdec seems to require a LL(2) parser else if (is_first(*token, RULE_FUNCDEC)) { result = parse_funcdec(ctx); diff --git a/src/utils/ast/ast_function.c b/src/utils/ast/ast_function.c index edd53e0..b0356c1 100644 --- a/src/utils/ast/ast_function.c +++ b/src/utils/ast/ast_function.c @@ -23,7 +23,7 @@ struct ast *ast_create_function(char *name, struct ast *value) if (!function_data) return NULL; - function_data->name = strdup(name); + function_data->name = name; function_data->value = value; return ast_create(AST_FUNCTION, function_data); diff --git a/src/utils/ast/ast_function.h b/src/utils/ast/ast_function.h index 9294295..f6171dc 100644 --- a/src/utils/ast/ast_function.h +++ b/src/utils/ast/ast_function.h @@ -9,18 +9,19 @@ struct ast_function /** - * Checks if the given AST node is an ast_function + * @brief: Checks if the given AST node is an ast_function */ bool ast_is_function(struct ast *node); /** - * Retrieves the function data from the given AST node. - * Assumes that the node is of type AST_function. + * @brief: Retrieves the function data from the given AST node. + * Assumes that the node is of type AST_function. */ struct ast_function *ast_get_function(struct ast *node); /** - * Creates a new AST node representing an AST_function + * @brief: Creates a new AST node representing an AST_function + * @warning: name must be already allocated. */ struct ast *ast_create_function(char *name, struct ast *value); /*