cirilisp/symtable.c

195 lines
4.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}