feat: full while/until loops support, important bug fixes and more tests
This commit is contained in:
parent
9e522b2a68
commit
f31fca4204
6 changed files with 85 additions and 37 deletions
|
|
@ -1,17 +1,13 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "execution.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../expansion/expansion.h"
|
||||
#include "../utils/ast/ast.h"
|
||||
#include "../utils/hash_map/hash_map.h"
|
||||
|
||||
// Refactored: delegates to helpers in execution_helpers.c
|
||||
|
|
@ -40,6 +36,8 @@ int execution(struct ast *ast, struct hash_map *vars)
|
|||
return exec_ast_list(ast_get_list(ast), vars);
|
||||
case AST_AND_OR:
|
||||
return exec_ast_and_or(ast_get_and_or(ast), vars);
|
||||
case AST_LOOP:
|
||||
return exec_ast_loop(ast_get_loop(ast), vars);
|
||||
default:
|
||||
return 127;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "execution_helpers.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -9,8 +8,6 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../expansion/expansion.h"
|
||||
#include "../utils/ast/ast.h"
|
||||
#include "../utils/hash_map/hash_map.h"
|
||||
#include "../utils/lists/lists.h"
|
||||
#include "../utils/vars/vars.h"
|
||||
|
|
@ -275,6 +272,17 @@ void unset_all_redir(struct list *redir_list)
|
|||
}
|
||||
}
|
||||
|
||||
int exec_ast_loop(struct ast_loop *loop_node, struct hash_map *vars)
|
||||
{
|
||||
int res = 0;
|
||||
while (execution(loop_node->condition, vars) == 0)
|
||||
{
|
||||
res = execution(loop_node->body, vars);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// --- Builtins ---
|
||||
|
||||
static int builtin_echo(char **argv)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ int exec_ast_command(struct ast_command *command, struct hash_map *vars);
|
|||
int exec_ast_if(struct ast_if *if_node, struct hash_map *vars);
|
||||
int exec_ast_list(struct ast_list *list_node, struct hash_map *vars);
|
||||
int exec_ast_and_or(struct ast_and_or *ao_node, struct hash_map *vars);
|
||||
int exec_ast_loop(struct ast_loop *loop_node, struct hash_map *vars);
|
||||
|
||||
void unset_all_redir(struct list *redir_list);
|
||||
#endif // EXECUTION_HELPERS_H
|
||||
|
|
|
|||
|
|
@ -101,17 +101,13 @@ static void add_first_redir(void)
|
|||
add_first(RULE_REDIRECTION, TOKEN_REDIR_RIGHT_PIPE);
|
||||
}
|
||||
|
||||
// === Functions
|
||||
|
||||
int grammar_init(void)
|
||||
// Adds only direct tokens to rules firsts into the firsts map
|
||||
static void add_firsts_tokens(void)
|
||||
{
|
||||
// Initialize the firsts map
|
||||
bool success = init_firsts_map();
|
||||
if (success != true)
|
||||
return false;
|
||||
|
||||
// Populate the firsts map
|
||||
// TODO CHECK ORDER
|
||||
// Redirection
|
||||
add_first_redir();
|
||||
// %RIP Matteo 30/01/2026
|
||||
// %RAX Guillem 30/01/2026 hehe
|
||||
|
||||
// If
|
||||
add_first(RULE_IF, TOKEN_IF);
|
||||
|
|
@ -127,7 +123,7 @@ int grammar_init(void)
|
|||
add_first(RULE_WHILE, TOKEN_WHILE);
|
||||
|
||||
// Until
|
||||
add_first(RULE_WHILE, TOKEN_UNTIL);
|
||||
add_first(RULE_UNTIL, TOKEN_UNTIL);
|
||||
|
||||
// Case
|
||||
add_first(RULE_CASE, TOKEN_CASE);
|
||||
|
|
@ -136,33 +132,57 @@ int grammar_init(void)
|
|||
add_first(RULE_CASE_ITEM, TOKEN_LEFT_PAREN);
|
||||
add_first(RULE_CASE_ITEM, TOKEN_WORD);
|
||||
|
||||
// Case clause
|
||||
add_firsts(RULE_CASE_CLAUSE, first(RULE_CASE_ITEM));
|
||||
// Shell command
|
||||
add_first(RULE_SHELL_COMMAND, TOKEN_LEFT_BRACKET);
|
||||
add_first(RULE_SHELL_COMMAND, TOKEN_LEFT_PAREN);
|
||||
|
||||
// Redirection
|
||||
add_first_redir();
|
||||
// %RIP Matteo 30/01/2026
|
||||
// %RAX Guillem 30/01/2026 hehe
|
||||
// Simple command
|
||||
add_first(RULE_SIMPLE_COMMAND, TOKEN_WORD);
|
||||
add_first(RULE_SIMPLE_COMMAND, TOKEN_EXPORT);
|
||||
|
||||
// Element
|
||||
add_first(RULE_ELEMENT, TOKEN_WORD);
|
||||
add_first(RULE_ELEMENT, TOKEN_ASSIGNMENT_WORD);
|
||||
add_firsts(RULE_ELEMENT, first(RULE_REDIRECTION));
|
||||
|
||||
// Prefix
|
||||
add_first(RULE_PREFIX, TOKEN_ASSIGNMENT_WORD);
|
||||
|
||||
// Pipeline
|
||||
add_first(RULE_PIPELINE, TOKEN_WORD);
|
||||
|
||||
// Compound list
|
||||
add_first(RULE_COMPOUND_LIST, TOKEN_NEWLINE);
|
||||
|
||||
// Input
|
||||
add_first(RULE_INPUT, TOKEN_NEWLINE);
|
||||
add_first(RULE_INPUT, TOKEN_EOF);
|
||||
|
||||
// Funcdec
|
||||
add_first(RULE_FUNCDEC, TOKEN_WORD);
|
||||
}
|
||||
|
||||
// Adds only firsts that depend on other rules to the firsts map
|
||||
// WARNING order matters
|
||||
static void add_firsts_rec(void)
|
||||
{
|
||||
// Case clause
|
||||
add_firsts(RULE_CASE_CLAUSE, first(RULE_CASE_ITEM));
|
||||
|
||||
// Element
|
||||
add_firsts(RULE_ELEMENT, first(RULE_REDIRECTION));
|
||||
|
||||
// Prefix
|
||||
add_firsts(RULE_PREFIX, first(RULE_REDIRECTION));
|
||||
|
||||
// Shell command
|
||||
add_firsts(RULE_SHELL_COMMAND, first(RULE_IF));
|
||||
add_firsts(RULE_SHELL_COMMAND, first(RULE_FOR));
|
||||
add_firsts(RULE_SHELL_COMMAND, first(RULE_WHILE));
|
||||
add_firsts(RULE_SHELL_COMMAND, first(RULE_UNTIL));
|
||||
add_firsts(RULE_SHELL_COMMAND, first(RULE_CASE));
|
||||
|
||||
// Simple command
|
||||
add_firsts(RULE_SIMPLE_COMMAND, first(RULE_PREFIX));
|
||||
add_first(RULE_SIMPLE_COMMAND, TOKEN_WORD);
|
||||
add_first(RULE_SIMPLE_COMMAND, TOKEN_EXPORT);
|
||||
|
||||
// Funcdec
|
||||
add_first(RULE_FUNCDEC, TOKEN_WORD);
|
||||
|
||||
// Command
|
||||
add_firsts(RULE_COMMAND, first(RULE_SIMPLE_COMMAND));
|
||||
|
|
@ -170,23 +190,33 @@ int grammar_init(void)
|
|||
add_firsts(RULE_COMMAND, first(RULE_FUNCDEC));
|
||||
|
||||
// Pipeline
|
||||
add_first(RULE_PIPELINE, TOKEN_WORD);
|
||||
add_firsts(RULE_PIPELINE, first(RULE_COMMAND));
|
||||
|
||||
// And Or
|
||||
add_firsts(RULE_AND_OR, first(RULE_PIPELINE));
|
||||
|
||||
// Compound list
|
||||
add_first(RULE_COMPOUND_LIST, TOKEN_NEWLINE);
|
||||
add_firsts(RULE_COMPOUND_LIST, first(RULE_AND_OR));
|
||||
|
||||
// List
|
||||
add_firsts(RULE_LIST, first(RULE_AND_OR));
|
||||
|
||||
// Input
|
||||
add_first(RULE_INPUT, TOKEN_NEWLINE);
|
||||
add_first(RULE_INPUT, TOKEN_EOF);
|
||||
add_firsts(RULE_INPUT, first(RULE_LIST));
|
||||
}
|
||||
|
||||
// === Functions
|
||||
|
||||
int grammar_init(void)
|
||||
{
|
||||
// Initialize the firsts map
|
||||
bool success = init_firsts_map();
|
||||
if (success != true)
|
||||
return false;
|
||||
|
||||
// Populate the firsts map
|
||||
add_firsts_tokens();
|
||||
add_firsts_rec();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ void ast_free(struct ast **node)
|
|||
case AST_ASSIGNMENT:
|
||||
ast_free_assignment(ast_get_assignment(*node));
|
||||
break;
|
||||
case AST_NEG:
|
||||
ast_free_neg(ast_get_neg(*node));
|
||||
break;
|
||||
case AST_LOOP:
|
||||
ast_free_loop(ast_get_loop(*node));
|
||||
break;
|
||||
case AST_VOID:
|
||||
case AST_END:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue