2019-01-08 22:19:29 +01:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2019-02-03 18:57:49 +01:00
|
|
|
|
#include <wchar.h>
|
|
|
|
|
#include <wctype.h>
|
|
|
|
|
#include <ctype.h>
|
2019-01-08 22:19:29 +01:00
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
|
#include "read.h"
|
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int isSerbAlpha(wchar_t c);
|
|
|
|
|
int isConstituent(wchar_t c);
|
|
|
|
|
int isMacroC(wchar_t c);
|
|
|
|
|
int isEscape(wchar_t c);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-09 19:55:51 +01:00
|
|
|
|
wint_t scanwc(FILE *stream);
|
|
|
|
|
wint_t unscanwc(wint_t c, FILE *stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
object getToken();
|
2019-02-09 23:54:56 +01:00
|
|
|
|
object macroFunction(wchar_t m, FILE *stream);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-19 09:49:55 +01:00
|
|
|
|
object Read(char *prompt, FILE *stream)
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
|
|
|
|
printf("%s", prompt);
|
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
wint_t c;
|
|
|
|
|
object result;
|
|
|
|
|
|
2019-02-09 23:54:56 +01:00
|
|
|
|
while (iswspace(c = scanwc(stream)))
|
2019-02-03 18:57:49 +01:00
|
|
|
|
;
|
2019-02-09 19:55:51 +01:00
|
|
|
|
if (c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
TYPE(result) = EOFObject;
|
|
|
|
|
}
|
|
|
|
|
else if (isMacroC(c))
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
result = macroFunction(c, stream);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
else if (isEscape(c) || isConstituent(c))
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
unscanwc(c, stream);
|
|
|
|
|
result = getToken(stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SIGERR(invalidCharacterError);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
if (TYPE(result) == unspecifiedObject)
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-19 09:49:55 +01:00
|
|
|
|
return Read("", stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
/* уколико улаз функције није прави објекат (на пример уколико је учитан
|
|
|
|
|
* коментар) покушавамо прочитати опет */
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
else
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
return result;
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int isSerbAlpha(wchar_t c)
|
|
|
|
|
{
|
|
|
|
|
return ((c) == L'Ђ') || (((c) >= L'Ј') && ((c) <= L'Ћ')) ||
|
|
|
|
|
(((c) >= L'Џ') && ((c) <= L'И')) || (((c) >= L'К') &&
|
|
|
|
|
((c) <= L'Ш')) || (((c) >= L'а') && ((c) <= L'и')) ||
|
|
|
|
|
(((c) >= L'к') && ((c) <= L'ш')) || ((c) == L'ђ') ||
|
|
|
|
|
((c >= L'ј') && (c <= L'ћ')) || (c == L'џ');
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int isConstituent(wchar_t c)
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
return isSerbAlpha(c) || iswdigit(c) || ((c) == L'!') || ((c) == L'$')
|
|
|
|
|
|| ((c) == L'&') || ((c) == L'*') || ((c) == L'+') ||
|
|
|
|
|
(((c) >= L'-') && ((c) <= L'/')) || (((c) >= L'<') &&
|
|
|
|
|
((c) <= L'@')) || ((c) == L'^') || ((c) == L'\\') ||
|
|
|
|
|
((c) == L'_') || ((c) == L'~') || ((c) == L',');
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int isMacroC(wchar_t c)
|
|
|
|
|
{
|
|
|
|
|
return ((c) == L'"') || ((c) == L'#') || ((c) == L'\'') ||
|
|
|
|
|
((c) == L'(') || ((c) == L')') || ((c) == L';') ||
|
|
|
|
|
((c) == L'`');
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int isEscape(wchar_t c)
|
|
|
|
|
{
|
|
|
|
|
return (c) == L'|';
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int bufferSize = 1024;
|
|
|
|
|
wchar_t *globalBuffer = NULL;
|
2019-01-22 16:22:00 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
wchar_t *getBuffer()
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
if (globalBuffer == NULL)
|
2019-01-22 16:22:00 +01:00
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
globalBuffer = malloc(bufferSize * sizeof(wchar_t));
|
2019-01-22 16:22:00 +01:00
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
return globalBuffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wchar_t *increaseBuffer()
|
|
|
|
|
{
|
|
|
|
|
bufferSize += 1024;
|
|
|
|
|
return realloc(globalBuffer, bufferSize);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 19:55:51 +01:00
|
|
|
|
int eofStatus = 0;
|
|
|
|
|
wint_t scanwc(FILE *stream)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
2019-02-09 19:55:51 +01:00
|
|
|
|
if (eofStatus)
|
2019-01-22 16:22:00 +01:00
|
|
|
|
{
|
2019-02-09 19:55:51 +01:00
|
|
|
|
return WEOF;
|
2019-01-22 16:22:00 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
2019-02-09 19:55:51 +01:00
|
|
|
|
wint_t c = getwc(stream);
|
|
|
|
|
if (c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
eofStatus = 1;
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-09 19:55:51 +01:00
|
|
|
|
wint_t unscanwc(wint_t c, FILE *stream)
|
|
|
|
|
{
|
|
|
|
|
if (c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
eofStatus = 1;
|
|
|
|
|
return WEOF;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return ungetwc(c, stream);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-04 01:14:41 +01:00
|
|
|
|
int validFracNum(char *s)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
2019-03-04 01:14:41 +01:00
|
|
|
|
char *endptr;
|
|
|
|
|
strtoll(s, &endptr, 10);
|
|
|
|
|
if (*endptr == '\0' && endptr != s)
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (*endptr == '/' && endptr != s)
|
|
|
|
|
{
|
|
|
|
|
char *denom = endptr + 1;
|
|
|
|
|
strtoll(denom, &endptr, 10);
|
|
|
|
|
if (*endptr == '\0' && endptr != denom)
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int validRealNum(char *s)
|
|
|
|
|
{
|
|
|
|
|
char *endptr;
|
|
|
|
|
strtold(s, &endptr);
|
|
|
|
|
if (*endptr == '\0')
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2019-01-22 16:22:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 23:54:56 +01:00
|
|
|
|
object getToken(FILE *stream)
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
|
|
|
|
object result;
|
2019-02-03 18:57:49 +01:00
|
|
|
|
wchar_t *buffer = getBuffer();
|
|
|
|
|
wint_t c;
|
|
|
|
|
int i = 0;
|
2019-02-09 23:54:56 +01:00
|
|
|
|
c = scanwc(stream);
|
2019-02-09 14:06:53 +01:00
|
|
|
|
buffer[0] = towlower(c);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
if (isEscape(c))
|
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
while ((c = scanwc(stream)) != WEOF && !isEscape(c))
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (i + 2 >= bufferSize)
|
|
|
|
|
{
|
|
|
|
|
increaseBuffer();
|
|
|
|
|
}
|
|
|
|
|
buffer[++i] = c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer[++i] = c;
|
|
|
|
|
buffer[++i] = L'\0';
|
2019-02-09 19:55:51 +01:00
|
|
|
|
if (c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
SIGERR(unexpectedEOFError);
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
while (isConstituent(c = scanwc(stream)))
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (i + 1 >= bufferSize)
|
|
|
|
|
{
|
|
|
|
|
increaseBuffer();
|
|
|
|
|
}
|
|
|
|
|
buffer[++i] = towlower(c);
|
|
|
|
|
}
|
2019-02-09 23:54:56 +01:00
|
|
|
|
unscanwc(c, stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
buffer[++i] = L'\0';
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
int n = wcstombs(NULL, buffer, 0) + 1;
|
|
|
|
|
char *s = malloc(n * sizeof(char));
|
|
|
|
|
wcstombs(s, buffer, n);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-03-04 01:14:41 +01:00
|
|
|
|
char *endptr;
|
|
|
|
|
if (validFracNum(s))
|
2019-01-20 23:48:12 +01:00
|
|
|
|
{
|
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
NUM_TYPE(result) = fractionNum;
|
2019-03-04 01:14:41 +01:00
|
|
|
|
NUM_NUMER(result) = strtoll(s, &endptr, 10);
|
|
|
|
|
NUM_DENOM(result) = *endptr == '/' ?
|
|
|
|
|
strtoll(endptr + 1, &endptr, 10) : 1;
|
2019-01-20 23:48:12 +01:00
|
|
|
|
result = shortenFractionNum(result);
|
|
|
|
|
}
|
2019-03-04 01:14:41 +01:00
|
|
|
|
else if (validRealNum(s))
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-01-14 03:16:25 +01:00
|
|
|
|
TYPE(result) = numberObject;
|
2019-01-20 23:48:12 +01:00
|
|
|
|
NUM_TYPE(result) = realNum;
|
2019-02-03 18:57:49 +01:00
|
|
|
|
NUM_REAL(result) = strtold(s, NULL);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
else
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-01-14 03:16:25 +01:00
|
|
|
|
TYPE(result) = symbolObject;
|
2019-02-03 18:57:49 +01:00
|
|
|
|
SYM(result) = malloc((strlen(s) + 1) * sizeof(char));
|
|
|
|
|
strcpy(SYM(result), s);
|
|
|
|
|
}
|
2019-03-23 14:10:16 +01:00
|
|
|
|
free(s);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wchar_t escapedWChar(wchar_t c)
|
|
|
|
|
{
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
case L'n':
|
|
|
|
|
return L'\n';
|
|
|
|
|
break;
|
|
|
|
|
case L't':
|
|
|
|
|
return L'\t';
|
|
|
|
|
break;
|
|
|
|
|
case L'\\':
|
|
|
|
|
return L'\\';
|
|
|
|
|
break;
|
|
|
|
|
case L'"':
|
|
|
|
|
return L'"';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return c;
|
|
|
|
|
break;
|
2019-01-08 22:19:29 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 23:54:56 +01:00
|
|
|
|
object dispatchedChar(wint_t c, FILE *stream)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
|
|
|
|
|
switch (c)
|
2019-01-20 14:12:47 +01:00
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
case L'\\':
|
|
|
|
|
TYPE(result) = charObject;
|
|
|
|
|
|
|
|
|
|
wchar_t *buffer = getBuffer();
|
|
|
|
|
int i = 0, n;
|
|
|
|
|
|
2019-02-09 23:54:56 +01:00
|
|
|
|
c = scanwc(stream);
|
2019-02-09 19:55:51 +01:00
|
|
|
|
if (c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
SIGERR(unexpectedEOFError);
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
if (!isConstituent(c))
|
2019-01-20 14:12:47 +01:00
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
CHR(result) = c;
|
2019-01-20 14:12:47 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
unscanwc(c, stream);
|
2019-02-13 12:09:35 +01:00
|
|
|
|
while ((c = scanwc(stream)) != WEOF &&
|
|
|
|
|
isConstituent(c))
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (i + 1 >= bufferSize)
|
|
|
|
|
{
|
|
|
|
|
increaseBuffer();
|
|
|
|
|
}
|
|
|
|
|
buffer[i++] = c;
|
|
|
|
|
}
|
2019-02-13 12:09:35 +01:00
|
|
|
|
unscanwc(c, stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
buffer[i] = L'\0';
|
|
|
|
|
n = wcslen(buffer);
|
|
|
|
|
if (n == 1)
|
|
|
|
|
{
|
|
|
|
|
CHR(result) = buffer[0];
|
|
|
|
|
}
|
|
|
|
|
else if (!wcscmp(buffer, L"размак"))
|
|
|
|
|
{
|
|
|
|
|
CHR(result) = L' ';
|
|
|
|
|
}
|
|
|
|
|
else if (!wcscmp(buffer, L"новиред"))
|
|
|
|
|
{
|
|
|
|
|
CHR(result) = L'\n';
|
|
|
|
|
}
|
|
|
|
|
else if (!wcscmp(buffer, L"табулар"))
|
|
|
|
|
{
|
|
|
|
|
CHR(result) = L'\t';
|
|
|
|
|
}
|
2019-02-28 23:43:33 +01:00
|
|
|
|
else if (!wcscmp(buffer, L"нул"))
|
|
|
|
|
{
|
|
|
|
|
CHR(result) = L'\0';
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SIGERR(invalidHashSequenceError);
|
|
|
|
|
}
|
2019-01-20 14:12:47 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
break;
|
|
|
|
|
case L'И':
|
|
|
|
|
case L'и':
|
|
|
|
|
TYPE(result) = boolObject;
|
|
|
|
|
BOOL(result) = 1;
|
|
|
|
|
break;
|
|
|
|
|
case L'Л':
|
|
|
|
|
case L'л':
|
|
|
|
|
TYPE(result) = boolObject;
|
|
|
|
|
BOOL(result) = 0;
|
|
|
|
|
break;
|
|
|
|
|
case L'|':
|
|
|
|
|
for (;;)
|
2019-01-08 22:19:29 +01:00
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
if (((c = scanwc(stream)) == L'|' &&
|
|
|
|
|
(c = scanwc(stream)) == L'#') || c == WEOF)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
TYPE(result) = unspecifiedObject;
|
|
|
|
|
break;
|
2019-02-19 09:49:55 +01:00
|
|
|
|
case L'!':
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
if ((c = scanwc(stream)) == L'\n' || c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
TYPE(result) = unspecifiedObject;
|
|
|
|
|
break;
|
2019-02-09 19:55:51 +01:00
|
|
|
|
case WEOF:
|
|
|
|
|
SIGERR(unexpectedEOFError);
|
2019-03-23 14:10:16 +01:00
|
|
|
|
break;
|
2019-02-03 18:57:49 +01:00
|
|
|
|
default:
|
|
|
|
|
SIGERR(invalidHashSequenceError);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-09 23:54:56 +01:00
|
|
|
|
object macroFunction(wchar_t m, FILE *stream)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
object *listCurrent;
|
|
|
|
|
object expression;
|
|
|
|
|
wchar_t *buffer;
|
2019-02-09 19:55:51 +01:00
|
|
|
|
wint_t c;
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
switch (m)
|
|
|
|
|
{
|
|
|
|
|
case L'(':
|
|
|
|
|
listCurrent = &result;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
2019-02-19 09:49:55 +01:00
|
|
|
|
object currentObject = Read("", stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
if (TYPE(currentObject) == errorObject &&
|
2019-02-18 23:20:44 +01:00
|
|
|
|
!strcmp(ERR(currentObject),
|
|
|
|
|
commonErrs[unmatchedParenError]))
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
2019-03-23 14:10:16 +01:00
|
|
|
|
deleteObject(currentObject);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
TYPE(*listCurrent) = nilObject;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-02-09 19:55:51 +01:00
|
|
|
|
else if (TYPE(currentObject) == EOFObject)
|
|
|
|
|
{
|
|
|
|
|
TYPE(*listCurrent) = nilObject;
|
|
|
|
|
deleteObject(result);
|
|
|
|
|
SIGERR(unexpectedEOFError);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TYPE(*listCurrent) = consObject;
|
|
|
|
|
CONS(*listCurrent) = malloc(sizeof(cons));
|
|
|
|
|
CAR(*listCurrent) = copyObject(currentObject);
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
listCurrent = &CDR(*listCurrent);
|
|
|
|
|
}
|
|
|
|
|
deleteObject(currentObject);
|
|
|
|
|
}
|
2019-01-08 22:19:29 +01:00
|
|
|
|
|
2019-01-20 14:12:47 +01:00
|
|
|
|
int noErrors = 1;
|
|
|
|
|
listCurrent = &result;
|
|
|
|
|
|
|
|
|
|
while (TYPE(*listCurrent) != nilObject)
|
|
|
|
|
{
|
|
|
|
|
if (TYPE(CAR(*listCurrent)) == errorObject)
|
|
|
|
|
{
|
|
|
|
|
noErrors = 0;
|
2019-02-03 18:57:49 +01:00
|
|
|
|
break;
|
2019-01-20 14:12:47 +01:00
|
|
|
|
}
|
|
|
|
|
listCurrent = &CDR(*listCurrent);
|
|
|
|
|
}
|
|
|
|
|
if (!noErrors)
|
|
|
|
|
{
|
2019-02-03 18:57:49 +01:00
|
|
|
|
object error = copyObject(CAR(*listCurrent));
|
2019-01-20 14:12:47 +01:00
|
|
|
|
deleteObject(result);
|
2019-02-18 23:20:44 +01:00
|
|
|
|
CPYERR(ERR(error));
|
2019-01-20 14:12:47 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
|
2019-02-06 16:44:39 +01:00
|
|
|
|
int properDotComb = 1, dotPlace = -1, length;
|
|
|
|
|
object *dot;
|
|
|
|
|
for (length = 0, listCurrent = &result; TYPE(*listCurrent) !=
|
|
|
|
|
nilObject; ++length, listCurrent = &CDR(*listCurrent))
|
|
|
|
|
{
|
|
|
|
|
if (TYPE(CAR(*listCurrent)) == symbolObject &&
|
|
|
|
|
!strcmp(SYM(CAR(*listCurrent)), "."))
|
|
|
|
|
{
|
|
|
|
|
if (dotPlace == -1)
|
|
|
|
|
{
|
|
|
|
|
dotPlace = length;
|
|
|
|
|
dot = listCurrent;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
properDotComb = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (dotPlace != -1)
|
|
|
|
|
{
|
|
|
|
|
if (dotPlace != length - 2 || dotPlace == 0)
|
|
|
|
|
{
|
|
|
|
|
properDotComb = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!properDotComb)
|
|
|
|
|
{
|
|
|
|
|
SIGERR(improperDotNotation);
|
|
|
|
|
}
|
|
|
|
|
if (dotPlace != -1 && properDotComb)
|
|
|
|
|
{
|
|
|
|
|
object tmp = copyObject(CAR(CDR(*dot)));
|
|
|
|
|
deleteObject(*dot);
|
|
|
|
|
*dot = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 18:57:49 +01:00
|
|
|
|
return result;
|
|
|
|
|
break;
|
|
|
|
|
case L')':
|
|
|
|
|
SIGERR(unmatchedParenError);
|
|
|
|
|
break;
|
|
|
|
|
case L'\'':
|
|
|
|
|
case L'`':
|
2019-02-19 09:49:55 +01:00
|
|
|
|
expression = Read("", stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
if (TYPE(expression) == errorObject)
|
|
|
|
|
{
|
2019-02-18 23:20:44 +01:00
|
|
|
|
CPYERR(ERR(expression));
|
2019-02-09 19:55:51 +01:00
|
|
|
|
}
|
|
|
|
|
else if (TYPE(expression) == EOFObject)
|
|
|
|
|
{
|
|
|
|
|
SIGERR(unexpectedEOFError);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TYPE(result) = consObject;
|
|
|
|
|
CONS(result) = malloc(sizeof(cons));
|
|
|
|
|
TYPE(CAR(result)) = symbolObject;
|
|
|
|
|
SYM(CAR(result)) = malloc((strlen("навод") + 1) *
|
|
|
|
|
sizeof(char));
|
|
|
|
|
strcpy(SYM(CAR(result)), "навод");
|
|
|
|
|
|
|
|
|
|
TYPE(CDR(result)) = consObject;
|
|
|
|
|
CONS(CDR(result)) = malloc(sizeof(cons));
|
|
|
|
|
CAR(CDR(result)) = expression;
|
|
|
|
|
|
|
|
|
|
TYPE(CDR(CDR(result))) = nilObject;
|
|
|
|
|
break;
|
|
|
|
|
case L';':
|
|
|
|
|
TYPE(result) = unspecifiedObject;
|
2019-02-09 23:54:56 +01:00
|
|
|
|
while ((c = scanwc(stream)) != L'\n' && c != WEOF)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
;
|
|
|
|
|
break;
|
|
|
|
|
case L'"':
|
|
|
|
|
buffer = getBuffer();
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
2019-02-09 23:54:56 +01:00
|
|
|
|
while ((c = scanwc(stream)) != L'"' && c != WEOF)
|
2019-02-03 18:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (i + 2 >= bufferSize)
|
|
|
|
|
{
|
|
|
|
|
increaseBuffer();
|
|
|
|
|
}
|
|
|
|
|
if (c == L'\\')
|
|
|
|
|
{
|
2019-02-09 23:54:56 +01:00
|
|
|
|
c = scanwc(stream);
|
2019-02-18 23:20:44 +01:00
|
|
|
|
if (c != L'\n')
|
|
|
|
|
{
|
|
|
|
|
buffer[i++] = escapedWChar(c);
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
buffer[i++] = c;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-09 19:55:51 +01:00
|
|
|
|
if (c == WEOF)
|
|
|
|
|
{
|
|
|
|
|
SIGERR(unexpectedEOFError);
|
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
buffer[i] = L'\0';
|
|
|
|
|
|
|
|
|
|
int n = wcstombs(NULL, buffer, 0) + 1;
|
|
|
|
|
char *s = malloc(n * sizeof(char));
|
|
|
|
|
wcstombs(s, buffer, n);
|
|
|
|
|
TYPE(result) = stringObject;
|
|
|
|
|
STR(result) = s;
|
|
|
|
|
break;
|
|
|
|
|
case L'#':
|
2019-02-09 23:54:56 +01:00
|
|
|
|
result = dispatchedChar(scanwc(stream), stream);
|
2019-02-03 18:57:49 +01:00
|
|
|
|
break;
|
2019-01-20 14:12:47 +01:00
|
|
|
|
}
|
2019-02-03 18:57:49 +01:00
|
|
|
|
|
2019-01-08 22:19:29 +01:00
|
|
|
|
return result;
|
|
|
|
|
}
|