Имплементирана табела симбола и иницијална функција
This commit is contained in:
parent
b28b911ac3
commit
508e5fc9e1
4
Makefile
4
Makefile
|
@ -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)
|
||||||
|
|
16
cirilisp.c
16
cirilisp.c
|
@ -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
169
eval.c
|
@ -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
23
init.c
Normal 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("/", ÷);
|
||||||
|
}
|
137
internals.c
Normal file
137
internals.c
Normal 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
6
internals.h
Normal 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
2
read.h
|
@ -1,3 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
object read(char *prompt);
|
object read(char *prompt);
|
||||||
|
|
130
symtable.c
Normal file
130
symtable.c
Normal 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
17
symtable.h
Normal 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 уколико симбол није функција или уколико не постоји
|
||||||
|
* */
|
Loading…
Reference in a new issue