forked from KolibriOS/kolibrios
Added new port TinyBasic
(An improved version in conjunction with ktcc can generate executable files.) git-svn-id: svn://kolibrios.org@8733 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user