diff --git a/src/parser/parser.c b/src/parser/parser.c index 30cecdd..5b47dda 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1,12 +1,60 @@ #include "parser.h" +#include #include +#include +#include +#include + +#include "lexer/lexer.h" +#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 struct ast *get_ast() { - return NULL; + struct list *result_list = NULL; + struct ast *current_node = NULL; + + char *token = peek_token(); + 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; } +// TODO struct ast *get_ast_str(char *command) { (void)command; diff --git a/src/parser/parsing_utils.c b/src/parser/parsing_utils.c new file mode 100644 index 0000000..de77af3 --- /dev/null +++ b/src/parser/parsing_utils.c @@ -0,0 +1,35 @@ +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; + } + + while (token != NULL && !isterminator(token[0])) + { + cmd_elements = list_append(cmd_elements, token); + token = pop_token(); + } + + if (token == NULL) + { + puts("Internal error: cannot get the following token"); + return NULL; + } + + struct ast *result = ast_create_cmd(cmd_elements); + return result; +} + +struct ast *parse_if_rule(void) +{ + return NULL; +} + +struct ast *parse_shell_command(void) +{ + return parse_if_rule(); +} diff --git a/src/parser/parsing_utils.h b/src/parser/parsing_utils.h new file mode 100644 index 0000000..0ba9370 --- /dev/null +++ b/src/parser/parsing_utils.h @@ -0,0 +1,24 @@ +/* @brief Parses a simple list of words (command and arguments) + * and returns the resulting ast + */ +struct ast *parse_simple_command(void); + +/* + */ +struct ast *parse_if_rule(void); + +/* + */ +struct ast *parse_shell_command(void); + +/* + */ +struct ast* parse_compound_list(void); + +/* + */ +struct ast* parse_and_or(void); + +/* + */ +struct ast* else_clause(void); diff --git a/src/utils/ast/ast.h b/src/utils/ast/ast.h index 3247ba5..49f0cf4 100644 --- a/src/utils/ast/ast.h +++ b/src/utils/ast/ast.h @@ -8,13 +8,14 @@ enum ast_type { AST_END, + AST_LIST, AST_IF, AST_CMD }; struct ast_cmd { - struct list *cmd; + struct list *cmd; // A list of words (char*) }; struct ast_if @@ -37,6 +38,11 @@ struct ast void *data; }; +struct ast_list +{ + struct list *children; // A list of ASTs (ast*) +}; + /** * Checks if the given AST node is an if statement. */ @@ -47,6 +53,11 @@ bool ast_is_if(struct ast *node); */ bool ast_is_cmd(struct ast *node); +/** + * Checks if the given AST node is a command. + */ +bool ast_is_list(struct ast *node); + /** * Retrieves the if statement data from the given AST node. * Assumes that the node is of type AST_IF. @@ -59,6 +70,12 @@ struct ast_if *ast_get_if(struct ast *node); */ struct ast_cmd *ast_get_cmd(struct ast *node); +/** + * Retrieves the command data from the given AST node. + * Assumes that the node is of type AST_LIST. + */ +struct ast_list *ast_get_list(struct ast *node); + /** * Creates a new AST node representing an if statement. */ @@ -70,4 +87,9 @@ struct ast *ast_create_if(struct ast *condition, struct ast *then_clause, */ struct ast *ast_create_cmd(struct list *cmd); +/** + * Creates a new AST node representing a list of ASTs + */ +struct ast* ast_create_list(struct list* ast_list); + #endif /* ! AST_H */