Потпуно преправљена read функција и додати булеани, карактери и стрингови
This commit is contained in:
		
							parent
							
								
									5b5f792f5d
								
							
						
					
					
						commit
						916d3683ff
					
				
					 4 changed files with 536 additions and 375 deletions
				
			
		
							
								
								
									
										91
									
								
								print.c
									
										
									
									
									
								
							
							
						
						
									
										91
									
								
								print.c
									
										
									
									
									
								
							| 
						 | 
					@ -10,7 +10,11 @@ char *errors[] =
 | 
				
			||||||
	"Објекат није примењив",
 | 
						"Објекат није примењив",
 | 
				
			||||||
	"Дељење нулом",
 | 
						"Дељење нулом",
 | 
				
			||||||
	"Функцији није прослеђен правилан број аргумената",
 | 
						"Функцији није прослеђен правилан број аргумената",
 | 
				
			||||||
	"Синтаксна грешка"
 | 
						"Пређена је максимална дубина рекурзије",
 | 
				
			||||||
 | 
						"Невалидан карактер",
 | 
				
			||||||
 | 
						"Невалидна тараба-секвенца",
 | 
				
			||||||
 | 
						"Неочекивани крај фајла",
 | 
				
			||||||
 | 
						"Неочекивана заграда",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void printValue(object input);
 | 
					void printValue(object input);
 | 
				
			||||||
| 
						 | 
					@ -21,7 +25,7 @@ void print(object input)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		fprintf(stderr, "\nГРЕШКА: %s\n\n", errors[ERR(input)]);
 | 
							fprintf(stderr, "\nГРЕШКА: %s\n\n", errors[ERR(input)]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else if (TYPE(input) != unspecifiedObject)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf("\n");
 | 
							printf("\n");
 | 
				
			||||||
		printValue(input);
 | 
							printValue(input);
 | 
				
			||||||
| 
						 | 
					@ -31,40 +35,12 @@ void print(object input)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void printValue(object input)
 | 
					void printValue(object input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (TYPE(input) == nilObject)
 | 
						switch (TYPE(input))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
						case nilObject:
 | 
				
			||||||
		printf("()");
 | 
							printf("()");
 | 
				
			||||||
	}
 | 
							break;
 | 
				
			||||||
	else if (TYPE(input) == numberObject)
 | 
						case consObject:
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (NUM_TYPE(input) == fractionNum)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			printf("%lld", NUM_NUMER(input));
 | 
					 | 
				
			||||||
			if (NUM_DENOM(input) != 1)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				printf("/%lld", NUM_DENOM(input));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			printf("%LF", NUM_REAL(input));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == procedureObject)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		printf("<процедура:%s>", PROC_TYPE(input) == builtinProc ?
 | 
					 | 
				
			||||||
				"уграђена" : "сложена");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == symbolObject)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		printf("%s", SYM(input));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == boolObject)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		printf("#%s", BOOL(input) ? "истинито" : "лажно");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == consObject)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		printf("(");
 | 
							printf("(");
 | 
				
			||||||
		object *currentCell = &input;
 | 
							object *currentCell = &input;
 | 
				
			||||||
		while (TYPE(*currentCell) == consObject)
 | 
							while (TYPE(*currentCell) == consObject)
 | 
				
			||||||
| 
						 | 
					@ -82,5 +58,52 @@ void printValue(object input)
 | 
				
			||||||
			printValue(*currentCell);
 | 
								printValue(*currentCell);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		printf(")");
 | 
							printf(")");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case numberObject:
 | 
				
			||||||
 | 
							if (NUM_TYPE(input) == fractionNum)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								printf("%lld", NUM_NUMER(input));
 | 
				
			||||||
 | 
								if (NUM_DENOM(input) != 1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									printf("/%lld", NUM_DENOM(input));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								printf("%LF", NUM_REAL(input));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case symbolObject:
 | 
				
			||||||
 | 
							printf("%s", SYM(input));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case procedureObject:
 | 
				
			||||||
 | 
							printf("<процедура:%s>", PROC_TYPE(input) == builtinProc ?
 | 
				
			||||||
 | 
									"уграђена" : "сложена");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case boolObject:
 | 
				
			||||||
 | 
							printf("#%s", BOOL(input) ? "и" : "л");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case stringObject:
 | 
				
			||||||
 | 
							printf("\"%s\"", STR(input));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case charObject:
 | 
				
			||||||
 | 
							printf("#\\");
 | 
				
			||||||
 | 
							switch (CHR(input))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case L' ':
 | 
				
			||||||
 | 
								printf("размак");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case L'\n':
 | 
				
			||||||
 | 
								printf("новиред");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case L'\t':
 | 
				
			||||||
 | 
								printf("табулар");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								printf("%lc", CHR(input));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										740
									
								
								read.c
									
										
									
									
									
								
							
							
						
						
									
										740
									
								
								read.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,353 +1,399 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <wchar.h>
 | 
				
			||||||
 | 
					#include <wctype.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <regex.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
#include "read.h"
 | 
					#include "read.h"
 | 
				
			||||||
#include "print.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum
 | 
					int isSerbAlpha(wchar_t c);
 | 
				
			||||||
{
 | 
					int isConstituent(wchar_t c);
 | 
				
			||||||
	undefinedToken,
 | 
					int isMacroC(wchar_t c);
 | 
				
			||||||
	numberFracToken,
 | 
					int isEscape(wchar_t c);
 | 
				
			||||||
	numberRealToken,
 | 
					 | 
				
			||||||
	symbolToken,
 | 
					 | 
				
			||||||
	boolToken,
 | 
					 | 
				
			||||||
	quoteToken,
 | 
					 | 
				
			||||||
	lParenthesisToken,
 | 
					 | 
				
			||||||
	rParenthesisToken
 | 
					 | 
				
			||||||
} tokenType;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _Token
 | 
					wchar_t scanwc(FILE *stream);
 | 
				
			||||||
{
 | 
					#define unscanwc(c,stream) ungetwc(c,stream);
 | 
				
			||||||
	tokenType type;
 | 
					object getToken();
 | 
				
			||||||
	char *lexeme;
 | 
					object macroFunction(wchar_t m);
 | 
				
			||||||
	struct _Token *next;
 | 
					 | 
				
			||||||
} token;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int completeExpression(token **tokenQueue);
 | 
					 | 
				
			||||||
char *readline();
 | 
					 | 
				
			||||||
void append(token **head, token *appendix);
 | 
					 | 
				
			||||||
token *lexLine(char *input);
 | 
					 | 
				
			||||||
object parseExpression(token **inputList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
token *tokenQueue = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
object read(char *prompt)
 | 
					object read(char *prompt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	printf("%s", prompt);
 | 
						printf("%s", prompt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!completeExpression(&tokenQueue))
 | 
						wint_t c;
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		char *input = readline();
 | 
					 | 
				
			||||||
		if (input == NULL) /* унесен је EOF */
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			printf("\nКрај улазног стрима.\nВоЗдра и дођите нам\
 | 
					 | 
				
			||||||
 опет!\n");
 | 
					 | 
				
			||||||
			exit(0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		append(&tokenQueue, lexLine(input));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return parseExpression(&tokenQueue);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int completeExpression(token **tokenQueue)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int result = 0, indentLevel = 0;
 | 
					 | 
				
			||||||
	token *current = *tokenQueue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (current != NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (current->type == lParenthesisToken)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			++indentLevel;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (current->type == rParenthesisToken)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (indentLevel == 0)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				token **deleteParen = tokenQueue;
 | 
					 | 
				
			||||||
				while (*deleteParen != current)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					deleteParen = &(*deleteParen)->next;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				*deleteParen = current->next;
 | 
					 | 
				
			||||||
				free(current);
 | 
					 | 
				
			||||||
				current = *deleteParen;
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (indentLevel == 1)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					result = 1;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				--indentLevel;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (indentLevel == 0 && current->type != quoteToken)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				result = 1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		current = current->next;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ssize_t bytesRead;
 | 
					 | 
				
			||||||
size_t nbytes = 2048;
 | 
					 | 
				
			||||||
char *buffer = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
char *readline()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (buffer == NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		buffer = (char *) malloc(nbytes + 1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	bytesRead = getline(&buffer, &nbytes, stdin);
 | 
					 | 
				
			||||||
	if (bytesRead == -1)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	buffer[strlen(buffer)-1] = '\0';
 | 
					 | 
				
			||||||
	/* Уклања завршни њу-лајн или ЕОФ у стрингу
 | 
					 | 
				
			||||||
	 * и копира стринг на ново место */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return buffer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void append(token **head, token *tail)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	token **current = head;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (*current != NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		current = &(*current)->next;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*current = tail;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void deleteTokenList(token *root)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (root->lexeme != NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		free(root->lexeme);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (root->next != NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		deleteTokenList(root->next);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(root);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
token *lexLine(char *input)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	regex_t regSpace, regTokenGeneral, regNumberFrac, regNumberReal,
 | 
					 | 
				
			||||||
		regLParenthesis, regRParenthesis, regSymbol, regQuote, regDot,
 | 
					 | 
				
			||||||
		regBool;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	regcomp(®Space, "^[[:space:]]*", REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®TokenGeneral,"^(\\(|\\)|'|[-,.+/*_\\\\=<>!&?[:alnum:]]+|\
 | 
					 | 
				
			||||||
\\|[[:print:]]+\\||\"[[:print:]]+\")", REG_EXTENDED);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const int nmatches = 1;
 | 
					 | 
				
			||||||
	regmatch_t a[nmatches];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	token *root = NULL, **new;
 | 
					 | 
				
			||||||
	new = &root;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int i = 0, n;
 | 
					 | 
				
			||||||
	n = strlen(input);
 | 
					 | 
				
			||||||
	regexec(®Space, input + i, nmatches, a, 0);
 | 
					 | 
				
			||||||
	i += a[0].rm_eo;
 | 
					 | 
				
			||||||
/* помера индекс да би се игнорисали почетни "вајт-спејс" карактери */
 | 
					 | 
				
			||||||
	while (i < n)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		*new = malloc(sizeof(token));
 | 
					 | 
				
			||||||
		(*new)->next = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!regexec(®TokenGeneral, input + i, nmatches, a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->lexeme = malloc((a[0].rm_eo + 1) *
 | 
					 | 
				
			||||||
					sizeof(char));
 | 
					 | 
				
			||||||
			strncpy((*new)->lexeme, input + i, a[0].rm_eo);
 | 
					 | 
				
			||||||
			(*new)->lexeme[a[0].rm_eo] = '\0';
 | 
					 | 
				
			||||||
			i += a[0].rm_eo;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
/* уколико се у реду нађе карактер који се не може прихватити, штампа се место
 | 
					 | 
				
			||||||
 * тог каракетера у реду и бришу се сви токени тог реда, функција враћа NULL*/
 | 
					 | 
				
			||||||
			fprintf(stderr, "Невалидан карактер на месту %d\n", i);
 | 
					 | 
				
			||||||
			(*new)->lexeme = NULL;
 | 
					 | 
				
			||||||
			deleteTokenList(root);
 | 
					 | 
				
			||||||
			return NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		regexec(®Space, input + i, nmatches, a, 0);
 | 
					 | 
				
			||||||
		i += a[0].rm_eo;
 | 
					 | 
				
			||||||
		new = &((*new)->next);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
/* у овој петљи су нађени сви токени у реду и њихови лексеми су копирани у
 | 
					 | 
				
			||||||
 * листу, међутим још није одређен њихов тип, нити чак то да су валидни */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	regcomp(®NumberFrac, "^[-+]?[[:digit:]]+(/[[:digit:]]+)?$",
 | 
					 | 
				
			||||||
			REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®NumberReal, "^[-+]?[[:digit:]]*,[[:digit:]]+$",
 | 
					 | 
				
			||||||
			REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®Symbol, "^([-+/*_\\\\=<>!&?[:alnum:]]+|\
 | 
					 | 
				
			||||||
\\|[[:print:]]+\\|)$", REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®Quote, "^'$", REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®LParenthesis, "^\\($", REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®RParenthesis, "^\\)$", REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®Dot, "^\\.$", REG_EXTENDED);
 | 
					 | 
				
			||||||
	regcomp(®Bool, "^(истинито|лажно)$", REG_EXTENDED);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	new = &root;
 | 
					 | 
				
			||||||
	while ((*new) != NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (!regexec(®NumberFrac, (*new)->lexeme, nmatches, a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = numberFracToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (!regexec(®NumberReal, (*new)->lexeme, nmatches, a,
 | 
					 | 
				
			||||||
			0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = numberRealToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (!regexec(®Bool, (*new)->lexeme, nmatches, a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = boolToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (!regexec(®Symbol, (*new)->lexeme, nmatches, a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = symbolToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (!regexec(®Quote, (*new)->lexeme, nmatches, a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = quoteToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (!regexec(®LParenthesis, (*new)->lexeme, nmatches,
 | 
					 | 
				
			||||||
			a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = lParenthesisToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (!regexec(®RParenthesis, (*new)->lexeme, nmatches,
 | 
					 | 
				
			||||||
			a, 0))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			(*new)->type = rParenthesisToken;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
/* уколико се неки токен не може класификовати, штампа се лексем тог токена,
 | 
					 | 
				
			||||||
 * бришу се сви нађени токени у реду, и враћа се NULL */
 | 
					 | 
				
			||||||
			fprintf(stderr, "Невалидан токен:\"%s\"\n",
 | 
					 | 
				
			||||||
					(*new)->lexeme);
 | 
					 | 
				
			||||||
			deleteTokenList(root);
 | 
					 | 
				
			||||||
			return NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		new = &((*new)->next);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return root;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
object parseExpression(token **inputList)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	object result;
 | 
						object result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	token input = **inputList;
 | 
						while (iswspace(c = scanwc(stdin)))
 | 
				
			||||||
	free(*inputList);
 | 
							;
 | 
				
			||||||
	*inputList = input.next;
 | 
						if (isMacroC(c))
 | 
				
			||||||
	/* скида први преостали токен са листе унесених, да би се могао
 | 
						{
 | 
				
			||||||
	 * прерадити */
 | 
							result = macroFunction(c);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (isEscape(c) || isConstituent(c))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							unscanwc(c, stdin);
 | 
				
			||||||
 | 
							result = getToken();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SIGERR(invalidCharacterError);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (input.type == numberFracToken)
 | 
						if (TYPE(result) == unspecifiedObject)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return read("");
 | 
				
			||||||
 | 
					/* уколико улаз функције није прави објекат (на пример уколико је учитан
 | 
				
			||||||
 | 
					 * коментар) покушавамо прочитати опет */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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'џ');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int isConstituent(wchar_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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',');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int isMacroC(wchar_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((c) == L'"') || ((c) == L'#') || ((c) == L'\'') ||
 | 
				
			||||||
 | 
							((c) == L'(') || ((c) == L')') || ((c) == L';') ||
 | 
				
			||||||
 | 
							((c) == L'`');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int isEscape(wchar_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (c) == L'|';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int bufferSize = 1024;
 | 
				
			||||||
 | 
					wchar_t *globalBuffer = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wchar_t *getBuffer()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (globalBuffer == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							globalBuffer = malloc(bufferSize * sizeof(wchar_t));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return globalBuffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wchar_t *increaseBuffer()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bufferSize += 1024;
 | 
				
			||||||
 | 
						return realloc(globalBuffer, bufferSize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wchar_t scanwc(FILE *stream)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wint_t c;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if ((c = fgetwc(stream)) == WEOF)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf("\nКрај улазног стрима.\nВоЗдра и дођите нам опет!\n");
 | 
				
			||||||
 | 
							exit(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int lengthDigitArray(char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; isdigit(s[i]); ++i)
 | 
				
			||||||
 | 
							;
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int isFracNumToken(char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int digitNum1 = lengthDigitArray(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (digitNum1 == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (s[digitNum1] == '\0')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (s[digitNum1] == '/')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int digitNum2 = lengthDigitArray(s + digitNum1 + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (digitNum2 == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (s[digitNum1 + 1 + digitNum2] == '\0')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int isRealNumToken(char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int digitNum1 = lengthDigitArray(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (digitNum1 == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (s[digitNum1] == '\0')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (s[digitNum1] == ',')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int digitNum2 = lengthDigitArray(s + digitNum1 + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (digitNum2 == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (s[digitNum1 + 1 + digitNum2] == '\0')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object getToken()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						object result;
 | 
				
			||||||
 | 
						wchar_t *buffer = getBuffer();
 | 
				
			||||||
 | 
						wint_t c;
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
						buffer[0] = c = scanwc(stdin);
 | 
				
			||||||
 | 
						if (isEscape(c))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							while (!isEscape(c = scanwc(stdin)))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (i + 2 >= bufferSize)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									increaseBuffer();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								buffer[++i] = c;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							buffer[++i] = c;
 | 
				
			||||||
 | 
							buffer[++i] = L'\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							while (isConstituent(c = scanwc(stdin)))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (i + 1 >= bufferSize)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									increaseBuffer();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								buffer[++i] = towlower(c);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							unscanwc(c, stdin);
 | 
				
			||||||
 | 
							buffer[++i] = L'\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int n = wcstombs(NULL, buffer, 0) + 1;
 | 
				
			||||||
 | 
						char *s = malloc(n * sizeof(char));
 | 
				
			||||||
 | 
						wcstombs(s, buffer, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (isFracNumToken(s))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		TYPE(result) = numberObject;
 | 
							TYPE(result) = numberObject;
 | 
				
			||||||
		NUM_TYPE(result) = fractionNum;
 | 
							NUM_TYPE(result) = fractionNum;
 | 
				
			||||||
		NUM_NUMER(result) = atoll(input.lexeme);
 | 
							NUM_NUMER(result) = atoll(s);
 | 
				
			||||||
		char *tmp;
 | 
							char *tmp;
 | 
				
			||||||
		NUM_DENOM(result) = (tmp = strchr(input.lexeme, '/')) == NULL ?
 | 
							NUM_DENOM(result) = (tmp = strchr(s, '/')) == NULL ?
 | 
				
			||||||
			1 : atoll(tmp + 1);
 | 
								1 : atoll(tmp + 1);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		result = shortenFractionNum(result);
 | 
							result = shortenFractionNum(result);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (input.type == boolToken)
 | 
						else if (isRealNumToken(s))
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		TYPE(result) = boolObject;
 | 
					 | 
				
			||||||
		BOOL(result) = !strcmp("истинито", input.lexeme) ? 1 : 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (input.type == numberRealToken)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		TYPE(result) = numberObject;
 | 
							TYPE(result) = numberObject;
 | 
				
			||||||
		NUM_TYPE(result) = realNum;
 | 
							NUM_TYPE(result) = realNum;
 | 
				
			||||||
		NUM_REAL(result) = strtold(input.lexeme, NULL);
 | 
							NUM_REAL(result) = strtold(s, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (input.type == symbolToken)
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		TYPE(result) = symbolObject;
 | 
							TYPE(result) = symbolObject;
 | 
				
			||||||
		SYM(result) = malloc((strlen(input.lexeme) + 1)
 | 
							SYM(result) = malloc((strlen(s) + 1) * sizeof(char));
 | 
				
			||||||
					* sizeof(char));
 | 
							strcpy(SYM(result), s);
 | 
				
			||||||
		/* Алокација стринга */
 | 
					 | 
				
			||||||
		strcpy(SYM(result), input.lexeme);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (input.type == quoteToken)
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wchar_t escapedWChar(wchar_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (c)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if ((*inputList)->type != rParenthesisToken)
 | 
						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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object dispatchedChar(wchar_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						object result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (c)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case L'\\':
 | 
				
			||||||
 | 
							TYPE(result) = charObject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wchar_t *buffer = getBuffer();
 | 
				
			||||||
 | 
							int i = 0, n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							c = scanwc(stdin);
 | 
				
			||||||
 | 
							if (!isConstituent(c))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			TYPE(result) = consObject;
 | 
								CHR(result) = c;
 | 
				
			||||||
			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)) = parseExpression(inputList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			TYPE(CDR(CDR(result))) = nilObject;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			TYPE(result) = errorObject;
 | 
								unscanwc(c, stdin);
 | 
				
			||||||
			ERR(result) = syntaxError;
 | 
								while (!iswspace(c = scanwc(stdin)))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (i + 1 >= bufferSize)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										increaseBuffer();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									buffer[i++] = c;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								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';
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									SIGERR(invalidHashSequenceError);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
/* уколико "'" оператер директно претходи затвореној загради није могуће
 | 
						case L'И':
 | 
				
			||||||
 * правилно га претворити у навод оператер стога се он изоставља из било којег
 | 
						case L'и':
 | 
				
			||||||
 * израза */
 | 
							TYPE(result) = boolObject;
 | 
				
			||||||
	}
 | 
							BOOL(result) = 1;
 | 
				
			||||||
	else if (input.type == lParenthesisToken)
 | 
							break;
 | 
				
			||||||
	{
 | 
						case L'Л':
 | 
				
			||||||
		object *listCurrent = &result;
 | 
						case L'л':
 | 
				
			||||||
 | 
							TYPE(result) = boolObject;
 | 
				
			||||||
		while ((*inputList)->type != rParenthesisToken)
 | 
							BOOL(result) = 0;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case L'|':
 | 
				
			||||||
 | 
							for (;;)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			TYPE(*listCurrent) = consObject;
 | 
					 | 
				
			||||||
			CONS(*listCurrent) = malloc(sizeof(cons));
 | 
					 | 
				
			||||||
			/* Алокација конс ћелије */
 | 
					 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			CAR(*listCurrent) = parseExpression(inputList);
 | 
								if ((c = scanwc(stdin)) == L'|' &&
 | 
				
			||||||
 | 
										(c = scanwc(stdin)) == L'#')
 | 
				
			||||||
			listCurrent = &CDR(*listCurrent);
 | 
								{
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							TYPE(result) = unspecifiedObject;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							SIGERR(invalidHashSequenceError);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TYPE(*listCurrent) = nilObject;
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		input = **inputList;
 | 
					object macroFunction(wchar_t m)
 | 
				
			||||||
		free(*inputList);
 | 
					{
 | 
				
			||||||
		*inputList = input.next;
 | 
						object result;
 | 
				
			||||||
 | 
						object *listCurrent;
 | 
				
			||||||
 | 
						object expression;
 | 
				
			||||||
 | 
						wchar_t *buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (m)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case L'(':
 | 
				
			||||||
 | 
							listCurrent = &result;
 | 
				
			||||||
 | 
							for (;;)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								object currentObject = read("");
 | 
				
			||||||
 | 
								if (TYPE(currentObject) == errorObject &&
 | 
				
			||||||
 | 
									ERR(currentObject) == unmatchedParenError)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									TYPE(*listCurrent) = nilObject;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									TYPE(*listCurrent) = consObject;
 | 
				
			||||||
 | 
									CONS(*listCurrent) = malloc(sizeof(cons));
 | 
				
			||||||
 | 
									CAR(*listCurrent) = copyObject(currentObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									listCurrent = &CDR(*listCurrent);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								deleteObject(currentObject);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int noErrors = 1;
 | 
							int noErrors = 1;
 | 
				
			||||||
		listCurrent = &result;
 | 
							listCurrent = &result;
 | 
				
			||||||
| 
						 | 
					@ -357,21 +403,81 @@ object parseExpression(token **inputList)
 | 
				
			||||||
			if (TYPE(CAR(*listCurrent)) == errorObject)
 | 
								if (TYPE(CAR(*listCurrent)) == errorObject)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				noErrors = 0;
 | 
									noErrors = 0;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			listCurrent = &CDR(*listCurrent);
 | 
								listCurrent = &CDR(*listCurrent);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!noErrors)
 | 
							if (!noErrors)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								object error = copyObject(CAR(*listCurrent));
 | 
				
			||||||
			deleteObject(result);
 | 
								deleteObject(result);
 | 
				
			||||||
			TYPE(result) = errorObject;
 | 
								SIGERR(ERR(error));
 | 
				
			||||||
			ERR(result) = syntaxError;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case L')':
 | 
				
			||||||
 | 
							SIGERR(unmatchedParenError);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case L'\'':
 | 
				
			||||||
 | 
						case L'`':
 | 
				
			||||||
 | 
							expression = read("");
 | 
				
			||||||
 | 
							if (TYPE(expression) == errorObject)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return expression;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
							while (scanwc(stdin) != L'\n')
 | 
				
			||||||
 | 
								;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case L'"':
 | 
				
			||||||
 | 
							buffer = getBuffer();
 | 
				
			||||||
 | 
							wchar_t c;
 | 
				
			||||||
 | 
							int i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while ((c = scanwc(stdin)) != L'"')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (i + 2 >= bufferSize)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									increaseBuffer();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (c == L'\\')
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									c = scanwc(stdin);
 | 
				
			||||||
 | 
									buffer[i++] = escapedWChar(c);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									buffer[i++] = c;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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'#':
 | 
				
			||||||
 | 
							result = dispatchedChar(scanwc(stdin));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (input.type == rParenthesisToken)
 | 
					
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		TYPE(result) = errorObject;
 | 
					 | 
				
			||||||
		ERR(result) = syntaxError;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	free(input.lexeme);
 | 
					 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										56
									
								
								util.c
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								util.c
									
										
									
									
									
								
							| 
						 | 
					@ -56,6 +56,11 @@ void deleteObject(object input)
 | 
				
			||||||
		free(SYM(input));
 | 
							free(SYM(input));
 | 
				
			||||||
		SYM(input) = NULL;
 | 
							SYM(input) = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						else if (TYPE(input) == stringObject && STR(input) != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							free(STR(input));
 | 
				
			||||||
 | 
							STR(input) = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	else if (TYPE(input) == procedureObject &&
 | 
						else if (TYPE(input) == procedureObject &&
 | 
				
			||||||
			PROC_TYPE(input) == compoundProc)
 | 
								PROC_TYPE(input) == compoundProc)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -79,32 +84,22 @@ object copyObject(object input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	object result;
 | 
						object result;
 | 
				
			||||||
	TYPE(result) = TYPE(input);
 | 
						TYPE(result) = TYPE(input);
 | 
				
			||||||
	if (TYPE(input) == errorObject)
 | 
						switch (TYPE(input))
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ERR(result) = ERR(input);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == numberObject)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		NUM(result) = NUM(input);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == symbolObject)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SYM(result) =
 | 
					 | 
				
			||||||
			malloc(sizeof(char) * (strlen(SYM(input)) + 1));
 | 
					 | 
				
			||||||
		strcpy(SYM(result), SYM(input));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if (TYPE(input) == consObject)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
						case consObject:
 | 
				
			||||||
		CONS(result) = malloc(sizeof(cons));
 | 
							CONS(result) = malloc(sizeof(cons));
 | 
				
			||||||
		CAR(result) = copyObject(CAR(input));
 | 
							CAR(result) = copyObject(CAR(input));
 | 
				
			||||||
		CDR(result) = copyObject(CDR(input));
 | 
							CDR(result) = copyObject(CDR(input));
 | 
				
			||||||
	}
 | 
							break;
 | 
				
			||||||
	else if (TYPE(input) == boolObject)
 | 
						case numberObject:
 | 
				
			||||||
	{
 | 
							NUM(result) = NUM(input);
 | 
				
			||||||
		BOOL(result) = BOOL(input);
 | 
							break;
 | 
				
			||||||
	}
 | 
						case symbolObject:
 | 
				
			||||||
	else if (TYPE(input) == procedureObject)
 | 
							SYM(result) =
 | 
				
			||||||
	{
 | 
								malloc(sizeof(char) * (strlen(SYM(input)) + 1));
 | 
				
			||||||
 | 
							strcpy(SYM(result), SYM(input));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case procedureObject:
 | 
				
			||||||
		PROC(result) = malloc(sizeof(procedure));
 | 
							PROC(result) = malloc(sizeof(procedure));
 | 
				
			||||||
		PROC_TYPE(result) = PROC_TYPE(input);
 | 
							PROC_TYPE(result) = PROC_TYPE(input);
 | 
				
			||||||
		if (PROC_TYPE(result) == builtinProc)
 | 
							if (PROC_TYPE(result) == builtinProc)
 | 
				
			||||||
| 
						 | 
					@ -118,6 +113,23 @@ object copyObject(object input)
 | 
				
			||||||
			PROC_COMP_BODY(result) =
 | 
								PROC_COMP_BODY(result) =
 | 
				
			||||||
				copyObject(PROC_COMP_BODY(input));
 | 
									copyObject(PROC_COMP_BODY(input));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case boolObject:
 | 
				
			||||||
 | 
							BOOL(result) = BOOL(input);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case stringObject:
 | 
				
			||||||
 | 
							STR(result) =
 | 
				
			||||||
 | 
								malloc(sizeof(char) * (strlen(STR(input)) + 1));
 | 
				
			||||||
 | 
							strcpy(STR(result), STR(input));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case charObject:
 | 
				
			||||||
 | 
							CHR(result) = CHR(input);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case errorObject:
 | 
				
			||||||
 | 
							ERR(result) = ERR(input);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								util.h
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								util.h
									
										
									
									
									
								
							| 
						 | 
					@ -1,14 +1,26 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <wchar.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE(x) ((x).type)
 | 
					#define TYPE(x) ((x).type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONS(x) ((x).value.consCell)
 | 
					#define CONS(x) ((x).value.consCell)
 | 
				
			||||||
#define CAR(x) (((x).value.consCell)->car)
 | 
					#define CAR(x) (((x).value.consCell)->car)
 | 
				
			||||||
#define CDR(x) (((x).value.consCell)->cdr)
 | 
					#define CDR(x) (((x).value.consCell)->cdr)
 | 
				
			||||||
#define SYM(x) ((x).value.symbol)
 | 
					#define SYM(x) ((x).value.symbol)
 | 
				
			||||||
 | 
					#define STR(x) ((x).value.string)
 | 
				
			||||||
 | 
					#define CHR(x) ((x).value.character)
 | 
				
			||||||
#define BOOL(x) ((x).value.boolean)
 | 
					#define BOOL(x) ((x).value.boolean)
 | 
				
			||||||
#define ERR(x) ((x).value.err)
 | 
					#define ERR(x) ((x).value.err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SIGERR(error) \
 | 
				
			||||||
 | 
					{\
 | 
				
			||||||
 | 
						object result;\
 | 
				
			||||||
 | 
						TYPE(result) = errorObject;\
 | 
				
			||||||
 | 
						ERR(result) = error;\
 | 
				
			||||||
 | 
						return result;\
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PROC(x) ((x).value.proc)
 | 
					#define PROC(x) ((x).value.proc)
 | 
				
			||||||
#define PROC_TYPE(x) ((x).value.proc->type)
 | 
					#define PROC_TYPE(x) ((x).value.proc->type)
 | 
				
			||||||
#define PROC_BUILTIN(x) ((x).value.proc->value.builtin)
 | 
					#define PROC_BUILTIN(x) ((x).value.proc->value.builtin)
 | 
				
			||||||
| 
						 | 
					@ -24,11 +36,14 @@
 | 
				
			||||||
typedef enum
 | 
					typedef enum
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nilObject,
 | 
						nilObject,
 | 
				
			||||||
 | 
						unspecifiedObject,
 | 
				
			||||||
	consObject,
 | 
						consObject,
 | 
				
			||||||
	numberObject,
 | 
						numberObject,
 | 
				
			||||||
	symbolObject,
 | 
						symbolObject,
 | 
				
			||||||
	procedureObject,
 | 
						procedureObject,
 | 
				
			||||||
	boolObject,
 | 
						boolObject,
 | 
				
			||||||
 | 
						stringObject,
 | 
				
			||||||
 | 
						charObject,
 | 
				
			||||||
	errorObject
 | 
						errorObject
 | 
				
			||||||
} dataType;
 | 
					} dataType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +56,10 @@ typedef enum
 | 
				
			||||||
	divisionByZeroError,
 | 
						divisionByZeroError,
 | 
				
			||||||
	argumentNumberError,
 | 
						argumentNumberError,
 | 
				
			||||||
	maxRecursionDepthError,
 | 
						maxRecursionDepthError,
 | 
				
			||||||
	syntaxError
 | 
						invalidCharacterError,
 | 
				
			||||||
 | 
						invalidHashSequenceError,
 | 
				
			||||||
 | 
						unexpectedEOFError,
 | 
				
			||||||
 | 
						unmatchedParenError,
 | 
				
			||||||
} error;
 | 
					} error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum
 | 
					typedef enum
 | 
				
			||||||
| 
						 | 
					@ -82,6 +100,8 @@ struct object
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		error err;
 | 
							error err;
 | 
				
			||||||
		char *symbol;
 | 
							char *symbol;
 | 
				
			||||||
 | 
							char *string;
 | 
				
			||||||
 | 
							wchar_t character;
 | 
				
			||||||
		cons *consCell;
 | 
							cons *consCell;
 | 
				
			||||||
		number num;
 | 
							number num;
 | 
				
			||||||
		procedure *proc;
 | 
							procedure *proc;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue