234 lines
4.6 KiB
C
234 lines
4.6 KiB
C
![]() |
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#include "util.h"
|
|||
|
|
|||
|
char *improperListError = "Конс објекат мора бити правилна листа да би\
|
|||
|
могао бити евалуиран";
|
|||
|
char *typeError = "Неправилан тип аргумента прослеђен функцији";
|
|||
|
char *unrecognizedSymbolError = "Непознати симбол";
|
|||
|
char *notApplicableError = "Објекат није примењив";
|
|||
|
char *divisionByZeroError = "Дељење нулом";
|
|||
|
char *argumentNumberError = "Функцији није прослеђен правилан број аргумената";
|
|||
|
|
|||
|
object apply(object function, object parameters);
|
|||
|
|
|||
|
object eval(object input)
|
|||
|
{
|
|||
|
object result;
|
|||
|
|
|||
|
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), "/"))
|
|||
|
{
|
|||
|
result = input;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
deleteObject(input);
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(result) = unrecognizedSymbolError;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (TYPE(input) == consObject)
|
|||
|
{
|
|||
|
if (!properList(input))
|
|||
|
{
|
|||
|
deleteObject(input);
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(result) = improperListError;
|
|||
|
}
|
|||
|
|
|||
|
object *currentCell = &input;
|
|||
|
int noErrors = 1;
|
|||
|
while (TYPE(*currentCell) != nilObject)
|
|||
|
{
|
|||
|
CAR(*currentCell) = eval(CAR(*currentCell));
|
|||
|
|
|||
|
if (TYPE(CAR(*currentCell)) == errorObject)
|
|||
|
{
|
|||
|
noErrors = 0;
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(result) = ERRMSG(CAR(*currentCell));
|
|||
|
break;
|
|||
|
}
|
|||
|
currentCell = &CDR(*currentCell);
|
|||
|
}
|
|||
|
|
|||
|
if (noErrors)
|
|||
|
{
|
|||
|
result = apply(CAR(input), CDR(input));
|
|||
|
}
|
|||
|
deleteObject(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;
|
|||
|
|
|||
|
if (TYPE(function) != symbolObject)
|
|||
|
{
|
|||
|
deleteObject(function);
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(result) = notApplicableError;
|
|||
|
}
|
|||
|
/* TODO Ово налажење ће се касније извршавати кроз табелу симбола */
|
|||
|
else if (!strcmp(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);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
deleteObject(function);
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(result) = improperListError;
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
ERRMSG(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;
|
|||
|
ERRMSG(result) = typeError;
|
|||
|
}
|
|||
|
else if (listLength(parameters) == 0)
|
|||
|
{
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(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;
|
|||
|
ERRMSG(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;
|
|||
|
ERRMSG(result) = typeError;
|
|||
|
}
|
|||
|
else if (listLength(parameters) == 0)
|
|||
|
{
|
|||
|
TYPE(result) = errorObject;
|
|||
|
ERRMSG(result) = argumentNumberError;
|
|||
|
}
|
|||
|
else if (listLength(parameters) == 1)
|
|||
|
{
|
|||
|
NUM(result) = 1/NUM(CAR(parameters));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
NUM(result) = NUM(CAR(parameters))/NUM(add(CDR(parameters)));
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|