summaryrefslogtreecommitdiff
path: root/42sh/src/parser/parser_utils.c
diff options
context:
space:
mode:
Diffstat (limited to '42sh/src/parser/parser_utils.c')
-rw-r--r--42sh/src/parser/parser_utils.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/42sh/src/parser/parser_utils.c b/42sh/src/parser/parser_utils.c
new file mode 100644
index 0000000..f30c60f
--- /dev/null
+++ b/42sh/src/parser/parser_utils.c
@@ -0,0 +1,147 @@
+#include "parser_utils.h"
+
+#include "ast/ast.h"
+#include "utils/libstring.h"
+
+void cleanup(struct ast *root, enum parser_state *state)
+{
+ if (root != NULL)
+ {
+ ast_free(root);
+ }
+ *state = ERROR;
+}
+
+int error_check(struct ast *root, enum parser_state *state, struct token next)
+{
+ if (next.type == TOKEN_ERROR || *state == ERROR)
+ {
+ cleanup(root, state);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+struct ast *assign_setup(struct token next)
+{
+ struct ast *root = ast_create(AST_ASSIGN);
+ if (root == NULL)
+ {
+ return NULL;
+ }
+ struct string *var_name = string_create(NULL);
+ struct string *value = string_create(NULL);
+
+ char *txt = next.value->data;
+
+ size_t i = 0;
+
+ while (txt[i] != '=')
+ {
+ if (!string_pushc(var_name, txt[i]))
+ {
+ string_free(var_name);
+ string_free(value);
+ // Noone will free it so we'll have to do it by ourselves
+ string_free(next.value);
+ ast_free(root);
+ return NULL;
+ }
+ i++;
+ }
+
+ i++;
+
+ while (txt[i] != '\0')
+ {
+ if (!string_pushc(value, txt[i]))
+ {
+ string_free(var_name);
+ string_free(value);
+ // Noone will free it so we'll have to do it by ourselves
+ string_free(next.value);
+ ast_free(root);
+ return NULL;
+ }
+ i++;
+ }
+
+ ((struct ast_assign *)root)->name = var_name;
+ ((struct ast_assign *)root)->val = value;
+
+ // Beause it will no be inside the ast, it won't be naturally freed
+ string_free(next.value);
+ return root;
+}
+
+size_t list_length(struct ast *lst)
+{
+ union ast_caster cast;
+ cast.ast = lst;
+ return cast.ast_l->nb_children;
+}
+
+// This is the function you're supposed to call when a keyword is considered
+// as a simple word
+void litteral_reserved_word(struct token *next)
+{
+ // This is pretty efficient thanks to the switch case statement
+ // I don't think there is a cleaner way to do this (37 lines)
+ switch (next->type)
+ {
+ case TOKEN_IF:
+ next->value = string_create("if");
+ return;
+ case TOKEN_THEN:
+ next->value = string_create("then");
+ return;
+ case TOKEN_ELIF:
+ next->value = string_create("elif");
+ return;
+ case TOKEN_ELSE:
+ next->value = string_create("else");
+ return;
+ case TOKEN_FI:
+ next->value = string_create("fi");
+ return;
+ case TOKEN_WHILE:
+ next->value = string_create("while");
+ return;
+ case TOKEN_UNTIL:
+ next->value = string_create("until");
+ return;
+ case TOKEN_DO:
+ next->value = string_create("do");
+ return;
+ case TOKEN_DONE:
+ next->value = string_create("done");
+ return;
+ case TOKEN_FOR:
+ next->value = string_create("for");
+ return;
+ case TOKEN_IN:
+ next->value = string_create("in");
+ return;
+ case TOKEN_NEG:
+ next->value = string_create("!");
+ return;
+ default:
+ // This catches any TOKEN_WORD and at this point, you're not even
+ // supposed to have anything else
+ return;
+ }
+}
+
+void clean_cons_tokens(enum token_type type, struct lexer *lexer)
+{
+ struct token next = lexer_peek(lexer);
+
+ while (next.type == type)
+ {
+ lexer_pop(lexer);
+ next = lexer_peek(lexer);
+ }
+}