summaryrefslogtreecommitdiff
path: root/42sh/src/parser/parser_lists.c
diff options
context:
space:
mode:
Diffstat (limited to '42sh/src/parser/parser_lists.c')
-rw-r--r--42sh/src/parser/parser_lists.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/42sh/src/parser/parser_lists.c b/42sh/src/parser/parser_lists.c
new file mode 100644
index 0000000..4b5e204
--- /dev/null
+++ b/42sh/src/parser/parser_lists.c
@@ -0,0 +1,128 @@
+#include <err.h>
+#include <stdio.h>
+
+#include "parser/parser_functions.h"
+#include "parser/parser_utils.h"
+
+struct ast *parse_list(struct lexer *lexer, enum parser_state *state)
+{
+ struct ast *node = parse_and_or(lexer, state);
+ struct ast *ast_list = NULL;
+
+ // Who forgot to check that node can be NULL, I sure did
+ if (node == NULL)
+ {
+ QUICK_CLEANUP
+ }
+
+ struct token next = lexer_peek(lexer);
+
+ size_t i = 0;
+
+ if (next.type == TOKEN_SEMICOLON)
+ {
+ ast_list = ast_create(AST_LIST);
+
+ if (ast_list == NULL)
+ {
+ cleanup(node, state);
+ return NULL;
+ }
+
+ set_left(ast_list, node);
+ i++;
+ }
+
+ // If we enter this loop, this means we have a list of more than 1 element
+ while (next.type == TOKEN_SEMICOLON)
+ {
+ lexer_pop(lexer);
+ next = lexer_peek(lexer);
+
+ // Case where we have only one ';', meaning it is the end of the list
+ if (next.type == TOKEN_EOF || next.type == TOKEN_NEWLINE)
+ {
+ // set_right(ast_list, NULL);
+ return ast_list;
+ }
+
+ struct ast *right = parse_and_or(lexer, state);
+ set_i(ast_list, right, i);
+ i++;
+
+ // Was checking if right was NULL, but in that case state is ERROR
+ // and error_check will catch it
+
+ next = lexer_peek(lexer);
+ if (error_check(ast_list, state, next))
+ {
+ return NULL;
+ }
+ }
+
+ return (ast_list == NULL) ? node : ast_list;
+}
+
+struct ast *parse_compound_list(struct lexer *lexer, enum parser_state *state)
+{
+ clean_cons_tokens(TOKEN_NEWLINE, lexer);
+
+ struct ast *node = parse_and_or(lexer, state);
+ struct ast *ast_lst = NULL;
+
+ struct token next = lexer_peek(lexer);
+
+ if (error_check(node, state, next))
+ {
+ return NULL;
+ }
+
+ size_t i = 0;
+
+ while (next.type == TOKEN_SEMICOLON || next.type == TOKEN_NEWLINE)
+ {
+ lexer_pop(lexer);
+
+ clean_cons_tokens(TOKEN_NEWLINE, lexer);
+ next = lexer_peek(lexer);
+
+ // This condition might need to be expanded in the future
+ // But I don't know if there is a better way to do this
+ if (next.type == TOKEN_THEN || next.type == TOKEN_FI
+ || next.type == TOKEN_ELSE || next.type == TOKEN_ELIF
+ || next.type == TOKEN_DO || next.type == TOKEN_DONE
+ || next.type == TOKEN_CURLY_RIGHT || next.type == TOKEN_PAR_LEFT)
+ {
+ return (ast_lst == NULL) ? node : ast_lst;
+ }
+
+ if (ast_lst == NULL)
+ {
+ ast_lst = ast_create(AST_LIST);
+ if (ast_lst == NULL)
+ {
+ cleanup(node, state);
+ return NULL;
+ }
+
+ set_left(ast_lst, node);
+ i++;
+ }
+
+ next = lexer_peek(lexer);
+
+ struct ast *right = parse_and_or(lexer, state);
+
+ // Can put the i++ in the set_i function but I'm too scared
+ set_i(ast_lst, right, i);
+ i++;
+
+ next = lexer_peek(lexer);
+ if (error_check(ast_lst, state, next))
+ {
+ return NULL;
+ }
+ }
+
+ return (ast_lst == NULL) ? node : ast_lst;
+}