From 80e4b6c2fdf13c0ebf2ec227bc1ebb5d6a6fee3a Mon Sep 17 00:00:00 2001 From: Guillem George Date: Wed, 14 Jan 2026 20:53:47 +0100 Subject: [PATCH] feat: suport for the new lexer and if/else structures --- src/parser/parser.c | 46 ++++----- src/parser/parsing_utils.c | 189 +++++++++++++++++++++++++++++++++---- src/parser/parsing_utils.h | 5 +- 3 files changed, 194 insertions(+), 46 deletions(-) diff --git a/src/parser/parser.c b/src/parser/parser.c index 5b47dda..2918445 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -10,25 +10,7 @@ #include "utils/lists/lists.h" // === Static functions - -/* Returns true if c is a command terminator, false otherwise - */ -static bool isterminator(char c) -{ - switch (c) - { - case '\n': - case ';': - case EOF: - return true; - default: - return false; - } -} - -/* Parses a simple list of words (command and arguments) - * and returns the resulting ast - */ +// ... // === Functions @@ -37,19 +19,29 @@ struct ast *get_ast() struct list *result_list = NULL; struct ast *current_node = NULL; - char *token = peek_token(); - if (token != NULL) + struct token *token = peek_token(); + + while (token != NULL && token->type != TOKEN_EOF) + { + switch (token->type) + { + case TOKEN_WORD: + struct ast *cmd = parse_simple_command(); + result_list = list_append(result_list, cmd); + break; + default: + // Forward + token = pop_token(); + break; + } + } + + if (token == NULL) { puts("Internal error: cannot get the following token"); return NULL; } - while (token[0] != EOF) - { - struct ast *cmd = parse_simple_command(); - result_list = list_append(result_list, cmd); - } - struct ast *result = ast_create_list(result_list); return result; } diff --git a/src/parser/parsing_utils.c b/src/parser/parsing_utils.c index de77af3..74ec36d 100644 --- a/src/parser/parsing_utils.c +++ b/src/parser/parsing_utils.c @@ -1,23 +1,65 @@ +// === Includes +#include "parsing_utils.h" + +#include +#include +#include + +#include "lexer/lexer.h" +#include "utils/ast/ast.h" + +// === Macros + +#define PEEK_TOKEN() \ + peek_token(); \ + if (token == NULL) \ + { \ + puts("Internal error: cannot get the following token"); \ + return NULL; \ + } + +#define POP_TOKEN() \ + pop_token(); \ + if (token == NULL) \ + { \ + puts("Internal error: cannot get the following token"); \ + return NULL; \ + } + +// === Static functions + +/* Returns true if c is a command terminator, false otherwise + */ +static bool isterminator(struct token *token) +{ + if (token == NULL) + return false; + + switch (token->type) + { + case TOKEN_NEWLINE: + case TOKEN_SEMICOLON: + case TOKEN_EOF: + return true; + default: + return false; + } +} + +// === Functions + +/* Parses a simple list of words (command and arguments) + * and returns the resulting ast + */ struct ast *parse_simple_command(void) { struct list *cmd_elements = NULL; - char *token = pop_token(); - if (token == NULL) // just in case ? - { - puts("Internal error: cannot get the following token"); - return NULL; - } + struct token *token = POP_TOKEN(); - while (token != NULL && !isterminator(token[0])) + while (!isterminator(token)) { - cmd_elements = list_append(cmd_elements, token); - token = pop_token(); - } - - if (token == NULL) - { - puts("Internal error: cannot get the following token"); - return NULL; + cmd_elements = list_append(cmd_elements, token->data); + token = POP_TOKEN(); } struct ast *result = ast_create_cmd(cmd_elements); @@ -26,10 +68,123 @@ struct ast *parse_simple_command(void) struct ast *parse_if_rule(void) { - return NULL; + // If condition + struct token *token = POP_TOKEN(); + + if (token->type != TOKEN_IF) + { + puts("Internal error: expected a if rule but token has different " + "type"); + return NULL; + } + + struct ast *condition_content = parse_compound_list(); + + // Then content + token = POP_TOKEN(); + + if (token->type != TOKEN_THEN) + { + puts("Expected the 'then' keyword but token has different type"); + return NULL; + } + + struct ast *then_content = parse_compound_list(); + + // Eventual else/elif clause(s) + struct ast *else_content = parse_else_clause(); + + token = POP_TOKEN(); + if (token->type != TOKEN_FI) + { + puts("Expected the 'fi' keyword but token has different type"); + // TODO free previous asts + return NULL; + } + + struct ast *result = + ast_create_if(condition_content, then_content, else_content); + if (result == NULL) + { + puts("Internal error: could not create a new AST (AST_IF)"); + // TODO free previous asts + return NULL; + } + + return result; +} + +struct ast *parse_compound_list(void) +{ + struct list *result_list = NULL; // ast* list + struct list *cmd_elements = NULL; // token* list + struct token *token = PEEK_TOKEN(); + + while (token->type != TOKEN_THEN || token->type != TOKEN_ELIF + || TOKEN_TYPE != TOKEN_ELSE) + { + // Parse simple command + if (token->type == TOKEN_SEMICOLON || token->type == TOKEN_NEWLINE) + { + // Stage (-> next command) + struct ast *command = ast_create_cmd(cmd_elements); + result_list = list_append(result_list, command); + cmd_elements = NULL; + } + + if (token->type == TOKEN_EOF) + { + puts("Syntax error: Unexpected end of stream"); // TODO pas très + // bien dit + return NULL; + } + + cmd_elements = list_append(cmd_elements, token->data); + token = POP_TOKEN(); + } + + struct ast *result = ast_create_list(result_list); + return result; +} + +struct ast *parse_else_clause(void) +{ + // Eventual elif content + token = PEEK_TOKEN(); + + struct ast *result = NULL; + + // TODO handle ELIF + // while (token->type == TOKEN_ELIF) + // { + // puts("ABORTING ELIF: Not implemented ma gueule"); + // token = POP_TOKEN(); // Forward + // } + + // Eventual else content + if (token->type == TOKEN_ELSE) + { + result = parse_compound_list(); + token = POP_TOKEN(); // Forward + } + + if (result == NULL) + result == ast_create_void(); + + return result; } struct ast *parse_shell_command(void) { - return parse_if_rule(); + struct token *token = PEEK_TOKEN(); + + switch (token->type) + { + case TOKEN_IF: + return parse_if_rule(); + + default: + puts("I think it's not implemented yet"); + return NULL; + } } diff --git a/src/parser/parsing_utils.h b/src/parser/parsing_utils.h index 0ba9370..6981a13 100644 --- a/src/parser/parsing_utils.h +++ b/src/parser/parsing_utils.h @@ -11,7 +11,8 @@ struct ast *parse_if_rule(void); */ struct ast *parse_shell_command(void); -/* +/* @brief parses commands inside if/else clauses and returns the corresponding + * AST list */ struct ast* parse_compound_list(void); @@ -21,4 +22,4 @@ struct ast* parse_and_or(void); /* */ -struct ast* else_clause(void); +struct ast* parse_else_clause(void);