#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); } }