Имплементирана табела симбола и иницијална функција

This commit is contained in:
kappa 2019-01-19 14:42:56 +01:00
parent b28b911ac3
commit 508e5fc9e1
10 changed files with 333 additions and 174 deletions

View file

@ -13,7 +13,7 @@ LDFLAGS = -lm -lc
CC = cc CC = cc
SRC = cirilisp.c read.c eval.c print.c util.c SRC = cirilisp.c read.c eval.c print.c util.c symtable.c internals.c init.c
OBJ = $(SRC:.c=.o) OBJ = $(SRC:.c=.o)
all: cirilisp all: cirilisp
@ -21,7 +21,7 @@ all: cirilisp
.c.o: .c.o:
$(CC) -c $(CFLAGS) $< $(CC) -c $(CFLAGS) $<
$(OBJ): util.h read.h eval.h print.h $(OBJ): util.h read.h eval.h print.h symtable.h internals.h init.h
cirilisp: $(OBJ) cirilisp: $(OBJ)
$(CC) -o $@ $(OBJ) $(LDFLAGS) $(CC) -o $@ $(OBJ) $(LDFLAGS)

View file

@ -1,25 +1,13 @@
#include <locale.h> #include "init.h"
#include <stdio.h>
#include <stdlib.h>
#include "util.h"
#include "read.h" #include "read.h"
#include "eval.h" #include "eval.h"
#include "print.h" #include "print.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
/* Омогућава библиотекама коришћеним у интерпретеру да протумаче српску ћирилицу */ init();
if (setlocale(LC_ALL, "sr_RS.utf8") == NULL)
{
fprintf(stderr, "locale couldn't be set to \"sr_RS.utf8\",\
check if you've enabled it on your system\n");
exit(0);
}
for (;;) for (;;)
{ {
print(eval(read("ШКЉ> "))); print(eval(read("ШКЉ> ")));
} }
} }

169
eval.c
View file

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include "util.h" #include "util.h"
#include "symtable.h"
object apply(object function, object parameters); object apply(object function, object parameters);
@ -12,11 +13,12 @@ object eval(object input)
if (TYPE(input) == nilObject || TYPE(input) == numberObject || if (TYPE(input) == nilObject || TYPE(input) == numberObject ||
TYPE(input) == errorObject) TYPE(input) == errorObject)
{
result = input; result = input;
}
else if (TYPE(input) == symbolObject) else if (TYPE(input) == symbolObject)
{ {
if (!strcmp(SYM(input), "+") || !strcmp(SYM(input), "-") || if (symbolExists(SYM(input)))
!strcmp(SYM(input), "*") || !strcmp(SYM(input), "/"))
{ {
result = input; result = input;
} }
@ -62,11 +64,6 @@ object eval(object input)
return result; return result;
} }
object add(object parameters);
object subtract(object parameters);
object multiply(object parameters);
object divide(object parameters);
object apply(object function, object parameters) object apply(object function, object parameters)
{ {
object result; object result;
@ -77,165 +74,21 @@ object apply(object function, object parameters)
TYPE(result) = errorObject; TYPE(result) = errorObject;
ERR(result) = notApplicableError; ERR(result) = notApplicableError;
} }
/* TODO Ово налажење ће се касније извршавати кроз табелу симбола */ else if (symbolExists(SYM(function)))
else if (!strcmp(SYM(function), "+"))
{ {
result = add(parameters); object(*f)();
} if ((f = internalFunction(SYM(function))) != NULL)
else if (!strcmp(SYM(function), "-")) {
{ result = f(parameters);
result = subtract(parameters); }
}
else if (!strcmp(SYM(function), "*"))
{
result = multiply(parameters);
}
else if (!strcmp(SYM(function), "/"))
{
result = divide(parameters);
} }
else else
{ {
deleteObject(function); deleteObject(function);
TYPE(result) = errorObject; TYPE(result) = errorObject;
ERR(result) = improperListError; ERR(result) = unrecognizedSymbolError;
} }
return result; return result;
} }
int allNumbers(object list)
{
object *currentCell = &list;
while (TYPE(*currentCell) != nilObject)
{
if (TYPE(CAR(*currentCell)) != numberObject)
{
return 0;
}
currentCell = &CDR(*currentCell);
}
return 1;
}
object add(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
NUM(result) = 0LL;
}
else
{
object first, rest;
first = CAR(parameters);
rest = add(CDR(parameters));
NUM(result) = NUM(first) + NUM(rest);
}
return result;
}
object subtract(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
}
else if (listLength(parameters) == 1)
{
NUM(result) = -NUM(CAR(parameters));
}
else
{
NUM(result) = NUM(CAR(parameters)) - NUM(add(CDR(parameters)));
}
return result;
}
object multiply(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
NUM(result) = 1LL;
}
else
{
object first, rest;
first = CAR(parameters);
rest = multiply(CDR(parameters));
NUM(result) = NUM(first) * NUM(rest);
}
return result;
}
object divide(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
}
else if (listLength(parameters) == 1)
{
if (NUM(CAR(parameters)) != 0)
{
NUM(result) = 1/NUM(CAR(parameters));
}
else
{
TYPE(result) = errorObject;
ERR(result) = divisionByZeroError;
}
}
else
{
if (NUM(add(CDR(parameters))) != 0)
{
NUM(result) = NUM(CAR(parameters))/NUM(add(CDR(parameters)));
}
else
{
TYPE(result) = errorObject;
ERR(result) = divisionByZeroError;
}
}
return result;
}

23
init.c Normal file
View file

@ -0,0 +1,23 @@
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include "symtable.h"
#include "internals.h"
void init()
{
if (setlocale(LC_ALL, "sr_RS.utf8") == NULL)
{
fprintf(stderr, "lokal se nije mogao podesiti na\
\"sr_RS.utf8\", proverite da li ste ga osposobili na vasem sistemu\n");
exit(0);
}
/* Омогућава библиотекама коришћеним у интерпретеру да протумаче српску
* ћирилицу */
addSymbolInternal("+", &add);
addSymbolInternal("-", &subtract);
addSymbolInternal("*", &multiply);
addSymbolInternal("/", &divide);
}

3
init.h Normal file
View file

@ -0,0 +1,3 @@
#pragma once
void init(void);

137
internals.c Normal file
View file

@ -0,0 +1,137 @@
#include "util.h"
int allNumbers(object list)
{
object *currentCell = &list;
while (TYPE(*currentCell) != nilObject)
{
if (TYPE(CAR(*currentCell)) != numberObject)
{
return 0;
}
currentCell = &CDR(*currentCell);
}
return 1;
}
object add(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
NUM(result) = 0LL;
}
else
{
object first, rest;
first = CAR(parameters);
rest = add(CDR(parameters));
NUM(result) = NUM(first) + NUM(rest);
}
return result;
}
object subtract(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
}
else if (listLength(parameters) == 1)
{
NUM(result) = -NUM(CAR(parameters));
}
else
{
NUM(result) = NUM(CAR(parameters)) - NUM(add(CDR(parameters)));
}
return result;
}
object multiply(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
NUM(result) = 1LL;
}
else
{
object first, rest;
first = CAR(parameters);
rest = multiply(CDR(parameters));
NUM(result) = NUM(first) * NUM(rest);
}
return result;
}
object divide(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNumbers(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
}
else if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
}
else if (listLength(parameters) == 1)
{
if (NUM(CAR(parameters)) != 0)
{
NUM(result) = 1/NUM(CAR(parameters));
}
else
{
TYPE(result) = errorObject;
ERR(result) = divisionByZeroError;
}
}
else
{
if (NUM(add(CDR(parameters))) != 0)
{
NUM(result) = NUM(CAR(parameters))/NUM(add(CDR(parameters)));
}
else
{
TYPE(result) = errorObject;
ERR(result) = divisionByZeroError;
}
}
return result;
}

6
internals.h Normal file
View file

@ -0,0 +1,6 @@
#pragma once
object add(object parameters);
object subtract(object parameters);
object multiply(object parameters);
object divide(object parameters);

2
read.h
View file

@ -1,3 +1,5 @@
#pragma once #pragma once
#include "util.h"
object read(char *prompt); object read(char *prompt);

130
symtable.c Normal file
View file

@ -0,0 +1,130 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "symtable.h"
typedef enum
{
internalSymbol,
objectSymbol
} symbolType;
typedef struct entry
{
symbolType type;
char *name;
union
{
object (*function)();
object definition;
} value;
struct entry *left;
struct entry *right;
} entry;
/* овај тип служи за имплементирање табеле симбола који могу бити дефинисани
* или путем интерне функције написане у интерпретеру, или је дефинисан
* коришћењем самог Ћирилисп интерпретера */
entry *root = NULL;
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;
}
/* случај у којем тражени симбол не постоји у табели, и случај у којем
* је он нађен враћају вредност на исти начин, али су гране тока
* одвојене ради читљивости */
}
int addSymbolInternal(char *symbol, object (*function)())
{
int status = 1;
entry **e = findEntry(&root, symbol);
if (*e == NULL)
{
*e = malloc(sizeof(entry));
(*e)->type = internalSymbol;
(*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1));
strcpy((*e)->name, symbol);
(*e)->value.function = function;
(*e)->left = (*e)->right = NULL;
}
else
{
status = 0;
}
return status;
}
int addSymbolDefinition(char *symbol, object definition)
{
int status = 1;
entry **e = findEntry(&root, symbol);
if (*e == NULL)
{
*e = malloc(sizeof(entry));
(*e)->type = objectSymbol;
(*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1));
strcpy((*e)->name, symbol);
(*e)->value.definition = copyObject(definition);
(*e)->left = (*e)->right = NULL;
}
else
{
status = 0;
}
return status;
}
int symbolExists(char *symbol)
{
int status = 1;
entry **e = findEntry(&root, symbol);
if (*e == NULL)
{
return 0;
}
else
{
return 1;
}
return status;
}
object (*internalFunction(char *symbol)) (object)
{
entry **e = findEntry(&root, symbol);
if (*e == NULL || (*e)->type != internalSymbol)
{
return NULL;
}
else
{
return ((*e)->value.function);
}
}

17
symtable.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include "util.h"
int addSymbolInternal(char *symbol, object (*function)());
int addSymbolDefinition(char *symbol, object definition);
/* служе за различите методе дефинисања нових симбола у језику
* враћају 1 уколико је нови симбол успешно додат, а 0 уколико није
* (постоји симбол са истим именом) */
int symbolExists(char *symbol);
/* враћа 1 уколико симбол постоји и 0 у супротном */
object (*internalFunction(char *symbol)) (object parameters);
/* враћа показивач на функцију уколико је симбол дефинисан као интерна
* функција, NULL уколико симбол није функција или уколико не постоји
* */