diff --git a/src/execution/execution.h b/src/execution/execution.h index 872f0ad..c3e0080 100644 --- a/src/execution/execution.h +++ b/src/execution/execution.h @@ -2,8 +2,8 @@ #define EXECUTION_H #include "../utils/ast/ast.h" -#include "../utils/lists/lists.h" #include "../utils/hash_map/hash_map.h" +#include "../utils/lists/lists.h" /** * @brief Execute the AST diff --git a/src/lexer/lexer_utils.c b/src/lexer/lexer_utils.c index 0a0a23d..4206c4c 100644 --- a/src/lexer/lexer_utils.c +++ b/src/lexer/lexer_utils.c @@ -98,6 +98,14 @@ static void set_token_keyword(struct token *tok, char *begin, ssize_t size) { tok->type = TOKEN_ELIF; } + else if (strncmp(begin, "&&", size) == 0) + { + tok->type = TOKEN_AND; + } + else if (strncmp(begin, "||", size) == 0) + { + tok->type = TOKEN_OR; + } // no keywords found. if (tok->type == TOKEN_NULL) diff --git a/src/lexer/lexer_utils.h b/src/lexer/lexer_utils.h index 729e912..83bc772 100644 --- a/src/lexer/lexer_utils.h +++ b/src/lexer/lexer_utils.h @@ -56,7 +56,9 @@ enum token_type TOKEN_THEN, TOKEN_ELSE, TOKEN_FI, - TOKEN_ELIF + TOKEN_ELIF, + TOKEN_AND, + TOKEN_OR }; struct token diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index dcb1f1b..b90cf68 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -7,6 +7,24 @@ #include "../utils/lists/lists.h" #include "grammar.h" +// === Static functions + +enum ast_and_or_type and_or_tok_to_ast(enum token_type tok_type) +{ + switch (tok_type) + { + case TOKEN_AND: + return AST_AND_OR_TYPE_AND; + case TOKEN_OR: + return AST_AND_OR_TYPE_OR; + default: + fprintf(stderr, "and_or impossible to init, wrong token type"); + return AST_AND_OR_NULL; + } +} + +// === Functions + struct ast *parse_list(struct lexer_context *ctx) { struct list *result_list = NULL; @@ -41,7 +59,37 @@ struct ast *parse_list(struct lexer_context *ctx) struct ast *parse_and_or(struct lexer_context *ctx) { - return parse_pipeline(ctx); + struct ast *result = parse_pipeline(ctx); + struct token *token = PEEK_TOKEN(); + + if (token->type == TOKEN_AND || token->type == TOKEN_OR) + { + // set left part + + struct ast *left = result; + + // eat and_or token + token = POP_TOKEN(); + + // set type + enum ast_and_or_type type = and_or_tok_to_ast(token->type); + + token = PEEK_TOKEN(); + + // skip newlines + while (token->type == TOKEN_NEWLINE) + { + token = POP_TOKEN(); + token = PEEK_TOKEN(); + } + + // right part + struct ast *right = parse_pipeline(ctx); + + result = ast_create_and_or(left, right, type); + } + + return result; } struct ast *parse_pipeline(struct lexer_context *ctx) @@ -190,31 +238,34 @@ struct ast *parse_compound_list(struct lexer_context *ctx) while (token->type == TOKEN_NEWLINE) { token = POP_TOKEN(); + token = PEEK_TOKEN(); } // and_or current_cmd = parse_and_or(ctx); if (current_cmd == NULL) return NULL; - list_append(result_list, current_cmd); + result_list = list_append(result_list, current_cmd); // Following commands token = PEEK_TOKEN(); while (token->type == TOKEN_SEMICOLON || token->type == TOKEN_NEWLINE) { POP_TOKEN(); + token = PEEK_TOKEN(); // Skip newlines while (token->type == TOKEN_NEWLINE) { token = POP_TOKEN(); + token = PEEK_TOKEN(); } // and_or current_cmd = parse_and_or(ctx); if (current_cmd == NULL) return NULL; - list_append(result_list, current_cmd); + result_list = list_append(result_list, current_cmd); token = PEEK_TOKEN(); } @@ -223,12 +274,14 @@ struct ast *parse_compound_list(struct lexer_context *ctx) if (token->type == TOKEN_SEMICOLON) { token = POP_TOKEN(); + token = PEEK_TOKEN(); } // Skip newlines while (token->type == TOKEN_NEWLINE) { token = POP_TOKEN(); + token = PEEK_TOKEN(); } struct ast *result = ast_create_list(result_list); @@ -276,8 +329,8 @@ struct ast *parse_else_clause(struct lexer_context *ctx) if (token->type == TOKEN_ELSE) { + token = POP_TOKEN(); // eat else result = parse_compound_list(ctx); - token = POP_TOKEN(); // Forward } if (result == NULL) diff --git a/src/utils/ast/ast.c b/src/utils/ast/ast.c index 4cfdf69..e336a73 100644 --- a/src/utils/ast/ast.c +++ b/src/utils/ast/ast.c @@ -2,10 +2,44 @@ #include "ast.h" +#include #include +#include #include #include +void ast_free(struct ast **node) +{ + if (*node == NULL) + return; + // ast void does not need to be freed. + if (ast_is_if(*node)) + ast_free_if(ast_get_if(*node)); + else if (ast_is_command(*node)) + ast_free_command(ast_get_command(*node)); + else if (ast_is_list(*node)) + ast_free_list(ast_get_list(*node)); + else if (ast_is_and_or(*node)) + ast_free_and_or(ast_get_and_or(*node)); + else if (ast_is_redir(*node)) + ast_free_redir(ast_get_redir(*node)); + + free(*node); + *node = NULL; +} + +struct ast *ast_create(enum ast_type type, void *data) +{ + struct ast *node = malloc(sizeof(struct ast)); + if (!node) + return NULL; + + node->type = type; + node->data = data; + + return node; +} + static void ast_print_dot_recursive(struct ast *node, FILE *out) { if (!node) @@ -13,6 +47,20 @@ static void ast_print_dot_recursive(struct ast *node, FILE *out) switch (node->type) { + case AST_LIST: { + struct ast_list *ast_list = ast_get_list(node); + fprintf(out, " node%p [label=\"LIST\"];\n", (void *)node); + + struct list *elt = ast_list->children; + while (elt != NULL) + { + struct ast *child = (struct ast *)elt->data; + fprintf(out, " node%p -> node%p;\n", (void *)node, (void *)child); + ast_print_dot_recursive(child, out); + elt = elt->next; + } + break; + } case AST_IF: { struct ast_if *if_data = ast_get_if(node); fprintf(out, " node%p [label=\"IF\"];\n", (void *)node); @@ -81,38 +129,4 @@ void ast_print_dot(struct ast *ast) ast_print_dot_recursive(ast, dot_pipe); fprintf(dot_pipe, "}\n"); pclose(dot_pipe); - - system("open ast.svg"); -} - -void ast_free(struct ast **node) -{ - if (*node == NULL) - return; - // ast void does not need to be freed. - if (ast_is_if(*node)) - ast_free_if(ast_get_if(*node)); - else if (ast_is_command(*node)) - ast_free_command(ast_get_command(*node)); - else if (ast_is_list(*node)) - ast_free_list(ast_get_list(*node)); - else if (ast_is_and_or(*node)) - ast_free_and_or(ast_get_and_or(*node)); - else if (ast_is_redir(*node)) - ast_free_redir(ast_get_redir(*node)); - - free(*node); - *node = NULL; -} - -struct ast *ast_create(enum ast_type type, void *data) -{ - struct ast *node = malloc(sizeof(struct ast)); - if (node == NULL) - return NULL; - - node->type = type; - node->data = data; - - return node; } diff --git a/src/utils/ast/ast_and_or.h b/src/utils/ast/ast_and_or.h index 7bbe76c..344cfbf 100644 --- a/src/utils/ast/ast_and_or.h +++ b/src/utils/ast/ast_and_or.h @@ -7,6 +7,7 @@ enum ast_and_or_type { + AST_AND_OR_NULL, AST_AND_OR_TYPE_AND, AST_AND_OR_TYPE_OR };