summaryrefslogtreecommitdiff
path: root/42sh/src/parser/parser_utils.c
blob: f30c60f9858fa72e38a7b41932cf2b6924bb250c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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);
    }
}