Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8733 | turbocat | 1 | /* |
2 | * Tiny BASIC |
||
3 | * Statement Handling Module |
||
4 | * |
||
5 | * Released as Public Domain by Damian Gareth Walker 2019 |
||
6 | * Created: 15-Aug-2019 |
||
7 | */ |
||
8 | |||
9 | |||
10 | /* included headers */ |
||
11 | #include |
||
12 | #include |
||
13 | #include |
||
14 | #include |
||
15 | #include "statement.h" |
||
16 | |||
17 | |||
18 | /* |
||
19 | * LET Statement Functions |
||
20 | */ |
||
21 | |||
22 | |||
23 | /* |
||
24 | * LET statement constructor |
||
25 | * returns: |
||
26 | * LetStatementNode* the created LET statement |
||
27 | */ |
||
28 | LetStatementNode *statement_create_let (void) { |
||
29 | |||
30 | /* local variables */ |
||
31 | LetStatementNode *letn; /* the created node */ |
||
32 | |||
33 | /* allocate memory and assign safe defaults */ |
||
34 | letn = malloc (sizeof (LetStatementNode)); |
||
35 | letn->variable = 0; |
||
36 | letn->expression = NULL; |
||
37 | |||
38 | /* return the LET statement node */ |
||
39 | return letn; |
||
40 | } |
||
41 | |||
42 | /* |
||
43 | * Destructor for a LET statement |
||
44 | * params: |
||
45 | * LetStatementNode *letn the doomed LET statement. |
||
46 | */ |
||
47 | void statement_destroy_let (LetStatementNode *letn) { |
||
48 | if (letn->expression) |
||
49 | expression_destroy (letn->expression); |
||
50 | free (letn); |
||
51 | } |
||
52 | |||
53 | |||
54 | /* |
||
55 | * IF Statement Functions |
||
56 | */ |
||
57 | |||
58 | |||
59 | /* |
||
60 | * IF statement constructor |
||
61 | * returns: |
||
62 | * IfStatementNode* the created IF statement |
||
63 | */ |
||
64 | IfStatementNode *statement_create_if (void) { |
||
65 | |||
66 | /* local variables */ |
||
67 | IfStatementNode *ifn; /* the created node */ |
||
68 | |||
69 | /* allocate memory and assign safe defaults */ |
||
70 | ifn = malloc (sizeof (IfStatementNode)); |
||
71 | ifn->left = ifn->right = NULL; |
||
72 | ifn->op = RELOP_EQUAL; |
||
73 | ifn->statement = NULL; |
||
74 | |||
75 | /* return the IF statement node */ |
||
76 | return ifn; |
||
77 | } |
||
78 | |||
79 | /* |
||
80 | * IF statement destructor |
||
81 | * params: |
||
82 | * IfStatementNode* ifn the doomed IF statement |
||
83 | */ |
||
84 | void statement_destroy_if (IfStatementNode *ifn) { |
||
85 | if (ifn->left) |
||
86 | expression_destroy (ifn->left); |
||
87 | if (ifn->right) |
||
88 | expression_destroy (ifn->right); |
||
89 | if (ifn->statement) |
||
90 | statement_destroy (ifn->statement); |
||
91 | free (ifn); |
||
92 | } |
||
93 | |||
94 | |||
95 | /* |
||
96 | * GOTO Statement Functions |
||
97 | */ |
||
98 | |||
99 | |||
100 | /* |
||
101 | * GOTO Statement Constructor |
||
102 | * returns: |
||
103 | * GotoStatementNode* the new GOTO statement |
||
104 | */ |
||
105 | GotoStatementNode *statement_create_goto (void) { |
||
106 | |||
107 | /* local variables */ |
||
108 | GotoStatementNode *goton; /* the statement to create */ |
||
109 | |||
110 | /* create and initialise the data */ |
||
111 | goton = malloc (sizeof (GotoStatementNode)); |
||
112 | goton->label = NULL; |
||
113 | |||
114 | /* return the goto statement */ |
||
115 | return goton; |
||
116 | } |
||
117 | |||
118 | /* |
||
119 | * GOTO Statement Destructor |
||
120 | * params: |
||
121 | * GotoStatementNode* goton the doomed GOTO statement |
||
122 | */ |
||
123 | void statement_destroy_goto (GotoStatementNode *goton) { |
||
124 | if (goton) { |
||
125 | if (goton->label) |
||
126 | expression_destroy (goton->label); |
||
127 | free (goton); |
||
128 | } |
||
129 | } |
||
130 | |||
131 | |||
132 | /* |
||
133 | * GOSUB Statement Functions |
||
134 | */ |
||
135 | |||
136 | |||
137 | /* |
||
138 | * GOSUB Statement Constructor |
||
139 | * returns: |
||
140 | * GosubStatementNode* the new GOSUB statement |
||
141 | */ |
||
142 | GosubStatementNode *statement_create_gosub (void) { |
||
143 | |||
144 | /* local variables */ |
||
145 | GosubStatementNode *gosubn; /* the statement to create */ |
||
146 | |||
147 | /* create and initialise the data */ |
||
148 | gosubn = malloc (sizeof (GosubStatementNode)); |
||
149 | gosubn->label = NULL; |
||
150 | |||
151 | /* return the gosub statement */ |
||
152 | return gosubn; |
||
153 | } |
||
154 | |||
155 | /* |
||
156 | * GOSUB Statement Destructor |
||
157 | * params: |
||
158 | * GosubStatementNode* gosubn the doomed GOSUB statement |
||
159 | */ |
||
160 | void statement_destroy_gosub (GosubStatementNode *gosubn) { |
||
161 | if (gosubn) { |
||
162 | if (gosubn->label) |
||
163 | expression_destroy (gosubn->label); |
||
164 | free (gosubn); |
||
165 | } |
||
166 | } |
||
167 | |||
168 | |||
169 | /* |
||
170 | * PRINT Statement Functions |
||
171 | */ |
||
172 | |||
173 | |||
174 | /* |
||
175 | * PRINT statement constructor |
||
176 | * returns: |
||
177 | * PrintStatementNode* the created PRINT statement |
||
178 | */ |
||
179 | PrintStatementNode *statement_create_print (void) { |
||
180 | |||
181 | /* local variables */ |
||
182 | PrintStatementNode *printn; /* the created node */ |
||
183 | |||
184 | /* allocate memory and assign safe defaults */ |
||
185 | printn = malloc (sizeof (PrintStatementNode)); |
||
186 | printn->first = NULL; |
||
187 | |||
188 | /* return the PRINT statement node */ |
||
189 | return printn; |
||
190 | } |
||
191 | |||
192 | /* |
||
193 | * Destructor for a PRINT statement |
||
194 | * params: |
||
195 | * PrintStatementNode *printn the doomed PRINT statement. |
||
196 | */ |
||
197 | void statement_destroy_print (PrintStatementNode *printn) { |
||
198 | OutputNode *current, *next; |
||
199 | current = printn->first; |
||
200 | while (current) { |
||
201 | next = current->next; |
||
202 | if (current->class == OUTPUT_STRING) |
||
203 | free (current->output.string); |
||
204 | else if (current->class == OUTPUT_EXPRESSION) |
||
205 | expression_destroy (current->output.expression); |
||
206 | free (current); |
||
207 | current = next; |
||
208 | } |
||
209 | free (printn); |
||
210 | } |
||
211 | |||
212 | |||
213 | /* |
||
214 | * INPUT Statement Functions |
||
215 | */ |
||
216 | |||
217 | |||
218 | /* |
||
219 | * INPUT statement constructor |
||
220 | * returns: |
||
221 | * InputStatementNode* initialised INPUT statement data |
||
222 | */ |
||
223 | InputStatementNode *statement_create_input (void) { |
||
224 | |||
225 | /* local variables */ |
||
226 | InputStatementNode *inputn; /* the new input statement data */ |
||
227 | |||
228 | /* allocate memory and initalise safely */ |
||
229 | inputn = malloc (sizeof (InputStatementNode)); |
||
230 | inputn->first = NULL; |
||
231 | |||
232 | /* return the created node */ |
||
233 | return inputn; |
||
234 | } |
||
235 | |||
236 | /* |
||
237 | * INPUT statement destructor |
||
238 | * params: |
||
239 | * InputStatementNode* inputn the doomed INPUT statement node |
||
240 | */ |
||
241 | void statement_destroy_input (InputStatementNode *inputn) { |
||
242 | |||
243 | /* local variables */ |
||
244 | VariableListNode |
||
245 | *variable, /* the current variable to destroy */ |
||
246 | *next; /* the next variable to destroy */ |
||
247 | |||
248 | /* delete the variables from the variable list, then the input node */ |
||
249 | if (inputn) { |
||
250 | variable = inputn->first; |
||
251 | while (variable) { |
||
252 | next = variable->next; |
||
253 | free (variable); |
||
254 | variable = next; |
||
255 | } |
||
256 | free (inputn); |
||
257 | } |
||
258 | } |
||
259 | |||
260 | |||
261 | /* |
||
262 | * Top Level Functions |
||
263 | */ |
||
264 | |||
265 | |||
266 | /* |
||
267 | * Statement constructor |
||
268 | * returns: |
||
269 | * StatementNode* the newly-created blank statement |
||
270 | */ |
||
271 | StatementNode *statement_create (void) { |
||
272 | |||
273 | /* local variables */ |
||
274 | StatementNode *statement; /* the created statement */ |
||
275 | |||
276 | /* allocate memory and set defaults */ |
||
277 | statement = malloc (sizeof (StatementNode)); |
||
278 | statement->class = STATEMENT_NONE; |
||
279 | |||
280 | /* return the created statement */ |
||
281 | return statement; |
||
282 | } |
||
283 | |||
284 | /* |
||
285 | * Statement destructor |
||
286 | * params: |
||
287 | * StatementNode* statement the doomed statement |
||
288 | */ |
||
289 | void statement_destroy (StatementNode *statement) { |
||
290 | switch (statement->class) { |
||
291 | case STATEMENT_LET: |
||
292 | statement_destroy_let (statement->statement.letn); |
||
293 | break; |
||
294 | case STATEMENT_PRINT: |
||
295 | statement_destroy_print (statement->statement.printn); |
||
296 | break; |
||
297 | case STATEMENT_INPUT: |
||
298 | statement_destroy_input (statement->statement.inputn); |
||
299 | break; |
||
300 | case STATEMENT_IF: |
||
301 | statement_destroy_if (statement->statement.ifn); |
||
302 | break; |
||
303 | case STATEMENT_GOTO: |
||
304 | statement_destroy_goto (statement->statement.goton); |
||
305 | break; |
||
306 | case STATEMENT_GOSUB: |
||
307 | statement_destroy_gosub (statement->statement.gosubn); |
||
308 | break; |
||
309 | default: |
||
310 | break; |
||
311 | } |
||
312 | free (statement); |
||
313 | } |
||
314 | |||
315 | |||
316 | /* |
||
317 | * Program Line Constructor |
||
318 | * returns: |
||
319 | * ProgramLineNode* the new program line |
||
320 | */ |
||
321 | ProgramLineNode *program_line_create (void) { |
||
322 | |||
323 | /* local variables */ |
||
324 | ProgramLineNode *program_line; /* the program line to create */ |
||
325 | |||
326 | /* create and initialise the program line */ |
||
327 | program_line = malloc (sizeof (ProgramLineNode)); |
||
328 | program_line->label = 0; |
||
329 | program_line->statement = NULL; |
||
330 | program_line->next = NULL; |
||
331 | |||
332 | /* return the new program line */ |
||
333 | return program_line; |
||
334 | } |
||
335 | |||
336 | /* |
||
337 | * Program Line Destructor |
||
338 | * params: |
||
339 | * ProgramLineNode* program_line the doomed program line |
||
340 | * params: |
||
341 | * ProgramLineNode* the next program line |
||
342 | */ |
||
343 | ProgramLineNode *program_line_destroy (ProgramLineNode *program_line) { |
||
344 | |||
345 | /* local variables */ |
||
346 | ProgramLineNode *next = NULL; /* the next program line */ |
||
347 | |||
348 | /* record the next line and destroy this one */ |
||
349 | if (program_line) { |
||
350 | next = program_line->next; |
||
351 | if (program_line->statement) |
||
352 | statement_destroy (program_line->statement); |
||
353 | free (program_line); |
||
354 | } |
||
355 | |||
356 | /* return the line following */ |
||
357 | return next; |
||
358 | } |
||
359 | |||
360 | /* |
||
361 | * Program Constructor |
||
362 | * returns: |
||
363 | * ProgramNode* the constructed program |
||
364 | */ |
||
365 | ProgramNode *program_create (void) { |
||
366 | |||
367 | /* local variables */ |
||
368 | ProgramNode *program; /* new program */ |
||
369 | |||
370 | /* create and initialise the program */ |
||
371 | program = malloc (sizeof (program)); |
||
372 | program->first = NULL; |
||
373 | |||
374 | /* return the new program */ |
||
375 | return program; |
||
376 | } |
||
377 | |||
378 | /* |
||
379 | * Program Destructor |
||
380 | * params: |
||
381 | * ProgramNode* program the doomed program |
||
382 | */ |
||
383 | void program_destroy (ProgramNode *program) { |
||
384 | |||
385 | /* local variables */ |
||
386 | ProgramLineNode *program_line; /* the program line to destroy */ |
||
387 | |||
388 | /* destroy the program lines, then the program itself */ |
||
389 | program_line = program->first; |
||
390 | while (program_line) |
||
391 | program_line = program_line_destroy (program_line); |
||
392 | free (program); |
||
393 | } |