From 508e5fc9e16967677804991dd3f181cbc6fb5ef3 Mon Sep 17 00:00:00 2001 From: kappa Date: Sat, 19 Jan 2019 14:42:56 +0100 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BC=D0=BF=D0=BB=D0=B5=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B8=D1=80=D0=B0=D0=BD=D0=B0=20=D1=82=D0=B0=D0=B1?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=20=D1=81=D0=B8=D0=BC=D0=B1=D0=BE=D0=BB=D0=B0?= =?UTF-8?q?=20=D0=B8=20=D0=B8=D0=BD=D0=B8=D1=86=D0=B8=D1=98=D0=B0=D0=BB?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=98=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 +- cirilisp.c | 16 +---- eval.c | 169 ++++------------------------------------------------ init.c | 23 +++++++ init.h | 3 + internals.c | 137 ++++++++++++++++++++++++++++++++++++++++++ internals.h | 6 ++ read.h | 2 + symtable.c | 130 ++++++++++++++++++++++++++++++++++++++++ symtable.h | 17 ++++++ 10 files changed, 333 insertions(+), 174 deletions(-) create mode 100644 init.c create mode 100644 init.h create mode 100644 internals.c create mode 100644 internals.h create mode 100644 symtable.c create mode 100644 symtable.h diff --git a/Makefile b/Makefile index d5d7f41..efbe299 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ LDFLAGS = -lm -lc 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) all: cirilisp @@ -21,7 +21,7 @@ all: cirilisp .c.o: $(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) $(CC) -o $@ $(OBJ) $(LDFLAGS) diff --git a/cirilisp.c b/cirilisp.c index 9c444fe..7f81872 100644 --- a/cirilisp.c +++ b/cirilisp.c @@ -1,25 +1,13 @@ -#include -#include -#include - -#include "util.h" +#include "init.h" #include "read.h" #include "eval.h" #include "print.h" int main(int argc, char **argv) { -/* Омогућава библиотекама коришћеним у интерпретеру да протумаче српску ћирилицу */ - 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); - } - + init(); for (;;) { print(eval(read("ШКЉ> "))); } } - diff --git a/eval.c b/eval.c index 71599a7..8f17980 100644 --- a/eval.c +++ b/eval.c @@ -3,6 +3,7 @@ #include #include "util.h" +#include "symtable.h" object apply(object function, object parameters); @@ -12,11 +13,12 @@ object eval(object input) if (TYPE(input) == nilObject || TYPE(input) == numberObject || TYPE(input) == errorObject) + { result = input; + } else if (TYPE(input) == symbolObject) { - if (!strcmp(SYM(input), "+") || !strcmp(SYM(input), "-") || - !strcmp(SYM(input), "*") || !strcmp(SYM(input), "/")) + if (symbolExists(SYM(input))) { result = input; } @@ -62,11 +64,6 @@ object eval(object input) 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 result; @@ -77,165 +74,21 @@ object apply(object function, object parameters) TYPE(result) = errorObject; ERR(result) = notApplicableError; } - /* TODO Ово налажење ће се касније извршавати кроз табелу симбола */ - else if (!strcmp(SYM(function), "+")) + else if (symbolExists(SYM(function))) { - result = add(parameters); - } - else if (!strcmp(SYM(function), "-")) - { - result = subtract(parameters); - } - else if (!strcmp(SYM(function), "*")) - { - result = multiply(parameters); - } - else if (!strcmp(SYM(function), "/")) - { - result = divide(parameters); + object(*f)(); + if ((f = internalFunction(SYM(function))) != NULL) + { + result = f(parameters); + } } else { deleteObject(function); TYPE(result) = errorObject; - ERR(result) = improperListError; + ERR(result) = unrecognizedSymbolError; } 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; -} diff --git a/init.c b/init.c new file mode 100644 index 0000000..8fa1f17 --- /dev/null +++ b/init.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#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("/", ÷); +} diff --git a/init.h b/init.h new file mode 100644 index 0000000..c6d8ff4 --- /dev/null +++ b/init.h @@ -0,0 +1,3 @@ +#pragma once + +void init(void); diff --git a/internals.c b/internals.c new file mode 100644 index 0000000..eb36f51 --- /dev/null +++ b/internals.c @@ -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; +} diff --git a/internals.h b/internals.h new file mode 100644 index 0000000..0895f28 --- /dev/null +++ b/internals.h @@ -0,0 +1,6 @@ +#pragma once + +object add(object parameters); +object subtract(object parameters); +object multiply(object parameters); +object divide(object parameters); diff --git a/read.h b/read.h index 14fdef7..ccff389 100644 --- a/read.h +++ b/read.h @@ -1,3 +1,5 @@ #pragma once +#include "util.h" + object read(char *prompt); diff --git a/symtable.c b/symtable.c new file mode 100644 index 0000000..f7f3cbc --- /dev/null +++ b/symtable.c @@ -0,0 +1,130 @@ +#include +#include +#include + +#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); + } +} diff --git a/symtable.h b/symtable.h new file mode 100644 index 0000000..5736008 --- /dev/null +++ b/symtable.h @@ -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 уколико симбол није функција или уколико не постоји + * */