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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
#ifndef AST_H
#define AST_H
#include <stdlib.h>
#include "ast/ast_redirect.h"
#include "lexer/token.h"
#include "utils/libstring.h"
/**
* @brief Each node type represent a class of elements from the SCL grammar.
*/
enum ast_node
{
// STEP 1
AST_COMMAND,
AST_IF,
AST_LOGICAL,
AST_LIST,
// STEP 2
AST_PIPELINE,
AST_REDIRECTION,
AST_WHILE,
AST_ASSIGN,
AST_FOR,
// STEP 3
AST_FUNCTION,
AST_SUBSHELL
};
/**
* @brief Base struct for the AST implementation.
*/
struct ast
{
enum ast_node type; /**< Type of the targeted AST. Used for inheritance. */
};
/**
* @brief AST which represent any kind of `command`.
* It can be a `shell command` or a `simple command`.
* Both are evaluated the same.
*/
struct ast_command
{
struct ast base; /**< Base struct for the AST implementation. */
struct string **args; /**< `args` used to call the given command. */
};
/**
* @brief AST which represent a `if/then/elif/else` block.
* An `if` statement may not contain an `elif` or an `else` block.
* If the `if` statement contains an `elif` block, it is stored as an
* `ast_if` in the `else_body`.
*/
struct ast_if
{
struct ast base; /**< Base struct for the AST implementation. */
struct ast *condition; /**< Contains the AST to evaluate as a condition. */
struct ast *then_body; /**< Contains the AST of the `then` block. */
struct ast *else_body; /**< Contains the AST of the `else` block. */
};
/**
* @brief AST which represent a shell list.
* A list can be either a `list` or a `compound list`.
* @note Although this struct contains a `nb_children` value,
* it is parsed as a binary tree, thus `nb_children` never exceeds 2.
*/
struct ast_list
{
struct ast base; /**< Base struct for the AST implementation. */
size_t nb_children; /**< Number of elements in the list */
struct ast **
children; /** Array of ASTs which represents the elements of the list */
};
/**
* @brief AST which represents any logical block.
* A logical block can be either a `not` block, a `and` block or a `or` block.
* The type of the logical block is determined by the `type` value.
* The `type` value can be either `TOKEN_AND`, `TOKEN_OR` or `TOKEN_NEG`.
* The binary logical operators are evaluated following the lazy method.
* @note If the `type` value is not one of the listed above, the evaluation
* of the tree will always exit this the code 1 and write to `stderr`.
*/
struct ast_logical
{
struct ast base; /**< Base struct for the AST implementation. */
enum token_type type; /**< Type of the logical operator. */
struct ast *left; /**< First block to be evaluated (always evaluated). */
struct ast *right; /**< Second block to be evaluated (may not be evaluated,
see `note`). */
};
/**
* @brief AST which represents a pipeline.
* The pipeline evaluation creates a context in which the output of
* `left` is redirected to the input of `right`.
*/
struct ast_pipeline
{
struct ast base; /**< Base struct for the AST implementation. */
struct ast *left; /**< The output of this AST is given to `right`. */
struct ast *right; /**< This AST gets its input from `left`. */
};
/**
* @brief AST used to represent redirections
* Redirect is a struct used to store info about this redirection
* Expr is the expression who the output shall be redirected
*/
struct ast_redirection
{
struct ast base; /**< Base struct for the AST implementation. */
struct redirect redirect;
struct ast *expr;
};
/**
* @brief AST used to represent the while loops (and also the until loops)
* Cond is the condition used to know if the loop shall still iterate
* Body is the tree to execute while the condition is still valid
*/
struct ast_while
{
struct ast base;
struct ast *cond;
struct ast *body;
};
/**
* @brief Struct used for variable assignment
* Name is the name of the variable
* Val is the value of said variable
*/
struct ast_assign
{
struct ast base;
struct string *name;
struct string *val;
};
/**
* @brief Left contains the args (the `in { WORD }` part).
* Right contains the body to execute.
*/
struct ast_for
{
struct ast base;
struct ast *left;
struct ast *right;
struct string *var;
};
/**
* @brief AST used for function definition.
* Name contains the name of the function
* Body contains the actual ast that will be executed each time
* the function is called
*/
struct ast_function
{
struct ast base;
struct string *name;
struct ast *body;
};
/**
* @brief AST used for subshell
* Body just contains the compound list to be executed in the subshell
*/
struct ast_subshell
{
struct ast base;
struct ast *body;
};
union ast_caster
{
struct ast *ast;
struct ast_command *ast_c;
struct ast_if *ast_i;
struct ast_list *ast_l;
struct ast_logical *ast_lo;
struct ast_pipeline *ast_p;
struct ast_redirection *ast_r;
struct ast_while *ast_w;
struct ast_assign *ast_a;
struct ast_for *ast_f;
struct ast_function *ast_func;
struct ast_subshell *ast_sub;
};
/**
* @brief Creates a heap-allocated AST of the size of ast_`type`.
* The AST is returned as a `struct ast*` but it can be casted into the right
* ast type struct.
* @param type The type of the AST to be created.
*/
struct ast *ast_create(enum ast_node type);
/**
* @brief Recursively frees the given AST. Any heap-allocated can be passed.
* @param ast The AST to be freed.
* @note This method does not exit when `ast` is `NULL`.
*/
void ast_free(struct ast *ast);
/**
* @brief Creates a file named `ast.dot` in the current folder which
* contains the DOT representation of the given AST.
* @param ast The AST to represent.
* @note This function is called only when the program is called with
* the `--pretty-print` flag.
*/
void pretty_print(struct ast *ast);
#endif /* ! AST_H */
|