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