diff options
Diffstat (limited to '42sh/src/parser/parser_utils.c')
| -rw-r--r-- | 42sh/src/parser/parser_utils.c | 147 |
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); + } +} |
