0,0 → 1,393 |
/* |
* Tiny BASIC |
* Statement Handling Module |
* |
* Released as Public Domain by Damian Gareth Walker 2019 |
* Created: 15-Aug-2019 |
*/ |
|
|
/* included headers */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <ctype.h> |
#include "statement.h" |
|
|
/* |
* LET Statement Functions |
*/ |
|
|
/* |
* LET statement constructor |
* returns: |
* LetStatementNode* the created LET statement |
*/ |
LetStatementNode *statement_create_let (void) { |
|
/* local variables */ |
LetStatementNode *letn; /* the created node */ |
|
/* allocate memory and assign safe defaults */ |
letn = malloc (sizeof (LetStatementNode)); |
letn->variable = 0; |
letn->expression = NULL; |
|
/* return the LET statement node */ |
return letn; |
} |
|
/* |
* Destructor for a LET statement |
* params: |
* LetStatementNode *letn the doomed LET statement. |
*/ |
void statement_destroy_let (LetStatementNode *letn) { |
if (letn->expression) |
expression_destroy (letn->expression); |
free (letn); |
} |
|
|
/* |
* IF Statement Functions |
*/ |
|
|
/* |
* IF statement constructor |
* returns: |
* IfStatementNode* the created IF statement |
*/ |
IfStatementNode *statement_create_if (void) { |
|
/* local variables */ |
IfStatementNode *ifn; /* the created node */ |
|
/* allocate memory and assign safe defaults */ |
ifn = malloc (sizeof (IfStatementNode)); |
ifn->left = ifn->right = NULL; |
ifn->op = RELOP_EQUAL; |
ifn->statement = NULL; |
|
/* return the IF statement node */ |
return ifn; |
} |
|
/* |
* IF statement destructor |
* params: |
* IfStatementNode* ifn the doomed IF statement |
*/ |
void statement_destroy_if (IfStatementNode *ifn) { |
if (ifn->left) |
expression_destroy (ifn->left); |
if (ifn->right) |
expression_destroy (ifn->right); |
if (ifn->statement) |
statement_destroy (ifn->statement); |
free (ifn); |
} |
|
|
/* |
* GOTO Statement Functions |
*/ |
|
|
/* |
* GOTO Statement Constructor |
* returns: |
* GotoStatementNode* the new GOTO statement |
*/ |
GotoStatementNode *statement_create_goto (void) { |
|
/* local variables */ |
GotoStatementNode *goton; /* the statement to create */ |
|
/* create and initialise the data */ |
goton = malloc (sizeof (GotoStatementNode)); |
goton->label = NULL; |
|
/* return the goto statement */ |
return goton; |
} |
|
/* |
* GOTO Statement Destructor |
* params: |
* GotoStatementNode* goton the doomed GOTO statement |
*/ |
void statement_destroy_goto (GotoStatementNode *goton) { |
if (goton) { |
if (goton->label) |
expression_destroy (goton->label); |
free (goton); |
} |
} |
|
|
/* |
* GOSUB Statement Functions |
*/ |
|
|
/* |
* GOSUB Statement Constructor |
* returns: |
* GosubStatementNode* the new GOSUB statement |
*/ |
GosubStatementNode *statement_create_gosub (void) { |
|
/* local variables */ |
GosubStatementNode *gosubn; /* the statement to create */ |
|
/* create and initialise the data */ |
gosubn = malloc (sizeof (GosubStatementNode)); |
gosubn->label = NULL; |
|
/* return the gosub statement */ |
return gosubn; |
} |
|
/* |
* GOSUB Statement Destructor |
* params: |
* GosubStatementNode* gosubn the doomed GOSUB statement |
*/ |
void statement_destroy_gosub (GosubStatementNode *gosubn) { |
if (gosubn) { |
if (gosubn->label) |
expression_destroy (gosubn->label); |
free (gosubn); |
} |
} |
|
|
/* |
* PRINT Statement Functions |
*/ |
|
|
/* |
* PRINT statement constructor |
* returns: |
* PrintStatementNode* the created PRINT statement |
*/ |
PrintStatementNode *statement_create_print (void) { |
|
/* local variables */ |
PrintStatementNode *printn; /* the created node */ |
|
/* allocate memory and assign safe defaults */ |
printn = malloc (sizeof (PrintStatementNode)); |
printn->first = NULL; |
|
/* return the PRINT statement node */ |
return printn; |
} |
|
/* |
* Destructor for a PRINT statement |
* params: |
* PrintStatementNode *printn the doomed PRINT statement. |
*/ |
void statement_destroy_print (PrintStatementNode *printn) { |
OutputNode *current, *next; |
current = printn->first; |
while (current) { |
next = current->next; |
if (current->class == OUTPUT_STRING) |
free (current->output.string); |
else if (current->class == OUTPUT_EXPRESSION) |
expression_destroy (current->output.expression); |
free (current); |
current = next; |
} |
free (printn); |
} |
|
|
/* |
* INPUT Statement Functions |
*/ |
|
|
/* |
* INPUT statement constructor |
* returns: |
* InputStatementNode* initialised INPUT statement data |
*/ |
InputStatementNode *statement_create_input (void) { |
|
/* local variables */ |
InputStatementNode *inputn; /* the new input statement data */ |
|
/* allocate memory and initalise safely */ |
inputn = malloc (sizeof (InputStatementNode)); |
inputn->first = NULL; |
|
/* return the created node */ |
return inputn; |
} |
|
/* |
* INPUT statement destructor |
* params: |
* InputStatementNode* inputn the doomed INPUT statement node |
*/ |
void statement_destroy_input (InputStatementNode *inputn) { |
|
/* local variables */ |
VariableListNode |
*variable, /* the current variable to destroy */ |
*next; /* the next variable to destroy */ |
|
/* delete the variables from the variable list, then the input node */ |
if (inputn) { |
variable = inputn->first; |
while (variable) { |
next = variable->next; |
free (variable); |
variable = next; |
} |
free (inputn); |
} |
} |
|
|
/* |
* Top Level Functions |
*/ |
|
|
/* |
* Statement constructor |
* returns: |
* StatementNode* the newly-created blank statement |
*/ |
StatementNode *statement_create (void) { |
|
/* local variables */ |
StatementNode *statement; /* the created statement */ |
|
/* allocate memory and set defaults */ |
statement = malloc (sizeof (StatementNode)); |
statement->class = STATEMENT_NONE; |
|
/* return the created statement */ |
return statement; |
} |
|
/* |
* Statement destructor |
* params: |
* StatementNode* statement the doomed statement |
*/ |
void statement_destroy (StatementNode *statement) { |
switch (statement->class) { |
case STATEMENT_LET: |
statement_destroy_let (statement->statement.letn); |
break; |
case STATEMENT_PRINT: |
statement_destroy_print (statement->statement.printn); |
break; |
case STATEMENT_INPUT: |
statement_destroy_input (statement->statement.inputn); |
break; |
case STATEMENT_IF: |
statement_destroy_if (statement->statement.ifn); |
break; |
case STATEMENT_GOTO: |
statement_destroy_goto (statement->statement.goton); |
break; |
case STATEMENT_GOSUB: |
statement_destroy_gosub (statement->statement.gosubn); |
break; |
default: |
break; |
} |
free (statement); |
} |
|
|
/* |
* Program Line Constructor |
* returns: |
* ProgramLineNode* the new program line |
*/ |
ProgramLineNode *program_line_create (void) { |
|
/* local variables */ |
ProgramLineNode *program_line; /* the program line to create */ |
|
/* create and initialise the program line */ |
program_line = malloc (sizeof (ProgramLineNode)); |
program_line->label = 0; |
program_line->statement = NULL; |
program_line->next = NULL; |
|
/* return the new program line */ |
return program_line; |
} |
|
/* |
* Program Line Destructor |
* params: |
* ProgramLineNode* program_line the doomed program line |
* params: |
* ProgramLineNode* the next program line |
*/ |
ProgramLineNode *program_line_destroy (ProgramLineNode *program_line) { |
|
/* local variables */ |
ProgramLineNode *next = NULL; /* the next program line */ |
|
/* record the next line and destroy this one */ |
if (program_line) { |
next = program_line->next; |
if (program_line->statement) |
statement_destroy (program_line->statement); |
free (program_line); |
} |
|
/* return the line following */ |
return next; |
} |
|
/* |
* Program Constructor |
* returns: |
* ProgramNode* the constructed program |
*/ |
ProgramNode *program_create (void) { |
|
/* local variables */ |
ProgramNode *program; /* new program */ |
|
/* create and initialise the program */ |
program = malloc (sizeof (program)); |
program->first = NULL; |
|
/* return the new program */ |
return program; |
} |
|
/* |
* Program Destructor |
* params: |
* ProgramNode* program the doomed program |
*/ |
void program_destroy (ProgramNode *program) { |
|
/* local variables */ |
ProgramLineNode *program_line; /* the program line to destroy */ |
|
/* destroy the program lines, then the program itself */ |
program_line = program->first; |
while (program_line) |
program_line = program_line_destroy (program_line); |
free (program); |
} |