2019-01-19 14:42:56 +01:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
|
#include "symtable.h"
|
|
|
|
|
|
|
|
|
|
typedef struct entry
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
2019-01-27 16:31:32 +01:00
|
|
|
|
object value;
|
2019-01-19 14:42:56 +01:00
|
|
|
|
struct entry *left;
|
|
|
|
|
struct entry *right;
|
|
|
|
|
} entry;
|
2019-01-27 16:31:32 +01:00
|
|
|
|
/* овај тип служи за имплементирање табеле симбола који помажу да се стварају
|
|
|
|
|
* променљиве и процедуре у ћирилиспу */
|
|
|
|
|
|
|
|
|
|
entry **tables = NULL;
|
|
|
|
|
#define GLOBALTABLE tables[0]
|
|
|
|
|
int currentTable = 0;
|
|
|
|
|
#define STACKMAX 1000
|
|
|
|
|
/* динамички алоцирани стек табела симбола, где tables[0] означава глобалну
|
|
|
|
|
* табелу симбола, а сваки наредни члан означава табелу која постоји у
|
|
|
|
|
* контексту друге, већ постојеће. на пример, уколико имамо процедуру "ф" која
|
|
|
|
|
* у себи дефиинише и извршава процедуру "г", током извршавања "г", tables[0],
|
|
|
|
|
* [1] и [2] ће редом означавати: глобалну табелу, табелу процедуре "ф" и
|
|
|
|
|
* табелу процедуре "г", када је "г" евалуирано и ток контроле се пребацује на
|
|
|
|
|
* "ф", tables[2] се брише као и сви симболи дефинисани у њој */
|
2019-01-19 14:42:56 +01:00
|
|
|
|
|
|
|
|
|
entry **findEntry(entry **current, char *symbol)
|
|
|
|
|
{
|
|
|
|
|
int cond;
|
|
|
|
|
|
|
|
|
|
if (*current == NULL)
|
|
|
|
|
{
|
|
|
|
|
return current;
|
|
|
|
|
}
|
|
|
|
|
else if ((cond = strcmp(symbol, (*current)->name)) < 0)
|
|
|
|
|
{
|
|
|
|
|
return findEntry(&(*current)->left, symbol);
|
|
|
|
|
}
|
|
|
|
|
else if (cond > 0)
|
|
|
|
|
{
|
|
|
|
|
return findEntry(&(*current)->right, symbol);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return current;
|
|
|
|
|
}
|
|
|
|
|
/* случај у којем тражени симбол не постоји у табели, и случај у којем
|
|
|
|
|
* је он нађен враћају вредност на исти начин, али су гране тока
|
|
|
|
|
* одвојене ради читљивости */
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-22 00:08:27 +01:00
|
|
|
|
void freeEntry(entry **current)
|
|
|
|
|
{
|
|
|
|
|
free((*current)->name);
|
2019-01-27 16:31:32 +01:00
|
|
|
|
deleteObject((*current)->value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createTableStack(int size)
|
|
|
|
|
{
|
|
|
|
|
tables = malloc(size * sizeof(entry *));
|
|
|
|
|
tables[0] = NULL;
|
|
|
|
|
currentTable = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int createTable()
|
|
|
|
|
{
|
|
|
|
|
if (currentTable >= STACKMAX)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
2019-01-22 00:08:27 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
tables[++currentTable] = NULL;
|
|
|
|
|
return 1;
|
2019-01-22 00:08:27 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
void removeTableAux(entry **table)
|
2019-01-22 00:08:27 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
free((*table)->name);
|
|
|
|
|
deleteObject((*table)->value);
|
|
|
|
|
if ((*table)->left != NULL)
|
|
|
|
|
{
|
|
|
|
|
removeTableAux(&(*table)->left);
|
|
|
|
|
free((*table)->left);
|
|
|
|
|
(*table)->left = NULL;
|
|
|
|
|
}
|
|
|
|
|
if ((*table)->right != NULL)
|
|
|
|
|
{
|
|
|
|
|
removeTableAux(&(*table)->right);
|
|
|
|
|
free((*table)->right);
|
|
|
|
|
(*table)->right = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
int removeTable()
|
|
|
|
|
{
|
|
|
|
|
if (currentTable <= 0)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
removeTableAux(&tables[currentTable--]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
void addSymbolInternal(char *symbol, object (*function)())
|
2019-01-19 14:42:56 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
entry **e = findEntry(&GLOBALTABLE, symbol);
|
2019-01-19 14:42:56 +01:00
|
|
|
|
|
2019-01-22 00:08:27 +01:00
|
|
|
|
if (*e != NULL)
|
2019-01-19 14:42:56 +01:00
|
|
|
|
{
|
2019-01-22 00:08:27 +01:00
|
|
|
|
freeEntry(e);
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-01-22 00:08:27 +01:00
|
|
|
|
*e = malloc(sizeof(entry));
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
TYPE((*e)->value) = procedureObject;
|
|
|
|
|
PROC((*e)->value) = malloc(sizeof(procedure));
|
|
|
|
|
PROC_TYPE((*e)->value) = builtinProc;
|
|
|
|
|
PROC_BUILTIN((*e)->value) = function;
|
2019-01-22 00:08:27 +01:00
|
|
|
|
(*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1));
|
|
|
|
|
strcpy((*e)->name, symbol);
|
|
|
|
|
(*e)->left = (*e)->right = NULL;
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
void addSymbolVariable(char *symbol, object variable)
|
2019-01-19 14:42:56 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
entry **e = findEntry(&tables[currentTable], symbol);
|
2019-01-19 14:42:56 +01:00
|
|
|
|
|
2019-01-22 00:08:27 +01:00
|
|
|
|
if (*e != NULL)
|
2019-01-19 14:42:56 +01:00
|
|
|
|
{
|
2019-01-22 00:08:27 +01:00
|
|
|
|
freeEntry(e);
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-01-22 00:08:27 +01:00
|
|
|
|
*e = malloc(sizeof(entry));
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
(*e)->value = copyObject(variable);
|
2019-01-22 00:08:27 +01:00
|
|
|
|
(*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1));
|
|
|
|
|
strcpy((*e)->name, symbol);
|
|
|
|
|
(*e)->left = (*e)->right = NULL;
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
int symbolExistsAux(int index, char *symbol)
|
2019-01-19 14:42:56 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
entry **e = findEntry(&tables[index], symbol);
|
2019-01-19 14:42:56 +01:00
|
|
|
|
|
|
|
|
|
if (*e == NULL)
|
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
if (index != 0)
|
|
|
|
|
{
|
|
|
|
|
return symbolExistsAux(index - 1, symbol);
|
|
|
|
|
}
|
2019-01-19 14:42:56 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
int symbolExists(char *symbol)
|
2019-01-19 14:42:56 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
return symbolExistsAux(currentTable, symbol);
|
2019-01-19 14:42:56 +01:00
|
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
object referVariableAux(int index, char *symbol)
|
2019-01-22 00:08:27 +01:00
|
|
|
|
{
|
|
|
|
|
object result;
|
2019-01-27 16:31:32 +01:00
|
|
|
|
entry **e = findEntry(&tables[index], symbol);
|
2019-01-22 00:08:27 +01:00
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
|
if (*e == NULL)
|
2019-01-22 00:08:27 +01:00
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
if (index != 0)
|
|
|
|
|
{
|
|
|
|
|
return referVariableAux(index - 1, symbol);
|
|
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
|
TYPE(result) = errorObject;
|
|
|
|
|
ERR(result) = unrecognizedSymbolError;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
|
result = (*e)->value;
|
2019-01-22 00:08:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-01-27 16:31:32 +01:00
|
|
|
|
|
|
|
|
|
object referVariable(char *symbol)
|
|
|
|
|
{
|
|
|
|
|
return referVariableAux(currentTable, symbol);
|
|
|
|
|
}
|