diff --git a/Makefile b/Makefile index f39c6e5..462167f 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ VERSION = 0.5 PREFIX = /usr/local # флегови за C компајлер и линкер -CFLAGS = -g -std=c99 -pedantic -Wall -O0 +CPPFLAGS = -D_POSIX_C_SOURCE=200809L +CFLAGS = -g -std=c99 -pedantic -Wall -O0 # CFLAGS = -std=c99 -pedantic -Wall -O1 LDFLAGS = -lm -lc @@ -19,7 +20,7 @@ OBJ = $(SRC:.c=.o) all: cirilisp .c.o: - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< $(OBJ): util.h read.h eval.h print.h symtable.h internals.h init.h diff --git a/read.c b/read.c index 1aaacb2..f1a4eec 100644 --- a/read.c +++ b/read.c @@ -1,4 +1,3 @@ -#define _POSIX_C_SOURCE 200809L #include #include #include @@ -132,123 +131,123 @@ void append(token **head, token *tail) *current = tail; } -regex_t regNumberFrac, regNumberReal, regLParenthesis, regRParenthesis, - regSpace, regSymbol, regQuote; -token *lex1Token(char *input, int *i) + +void deleteTokenList(token *root) { - token *result = malloc(sizeof(token)); - result->next = NULL; - - regcomp(®Space, "^[[:space:]]*", REG_EXTENDED); - - regcomp(®NumberFrac, "^[-+]?[[:digit:]]+(/[[:digit:]]+)?", - REG_EXTENDED); - regcomp(®NumberReal, "^[-+]?[[:digit:]]*,[[:digit:]]+", - REG_EXTENDED); - regcomp(®Symbol, "^[-+/*_\\\\=<>!&?[:alnum:]]+", REG_EXTENDED); - regcomp(®Quote, "^'", REG_EXTENDED); - regcomp(®LParenthesis, "^\\(", REG_EXTENDED); - regcomp(®RParenthesis, "^\\)", REG_EXTENDED); - - const int nmatches = 1; - regmatch_t a[nmatches]; - - regexec(®Space, input + *i, nmatches, a, 0); - *i += a[0].rm_eo; -/* помера индекс да би се игнорисали почетни "вајт-спејс" карактери */ - - if (!regexec(®NumberReal, input + *i, nmatches, a, 0)) + if (root->lexeme != NULL) { - result->type = numberRealToken; + free(root->lexeme); } - else if (!regexec(®Symbol, input + *i, nmatches, a, 0)) - { - int tmp = a[0].rm_eo; - if (!regexec(®NumberFrac, input + *i, nmatches, a, 0) && - tmp == a[0].rm_eo) -/* симбол може садржати цифре на било којој позицији али не може сам бити број - * не постоји погодан начина да се ово путем regex-a запише стога овај if - * исказ */ - { - result->type = numberFracToken; - } - else - { - regexec(®Symbol, input + *i, nmatches, a, 0); -/* претходни regexec позив је променио вредност a[0].rm_eo, овиме се она враћа - * на дужину нађеног симбола */ - result->type = symbolToken; - } - } - else if (!regexec(®NumberFrac, input + *i, nmatches, a, 0)) - { - result->type = numberFracToken; - } - else if (!regexec(®Quote, input + *i, nmatches, a, 0)) - { - result->type = quoteToken; - } - else if (!regexec(®LParenthesis, input + *i, nmatches, a, 0)) - { - result->type = lParenthesisToken; - } - else if (!regexec(®RParenthesis, input + *i, nmatches, a, 0)) - { - result->type = rParenthesisToken; - } - else - { - result->type = undefinedToken; - result->lexeme = NULL; - goto skipStringCopy; - } - result->lexeme = malloc((a[0].rm_eo + 1) * sizeof(char)); - strncpy(result->lexeme, input + *i, a[0].rm_eo); - result->lexeme[a[0].rm_eo] = '\0'; - *i += a[0].rm_eo; - regexec(®Space, input + *i, nmatches, a, 0); - *i += a[0].rm_eo; -/* игнорисање крајњих вајт-спејс карактера */ + if (root->next != NULL) + { + deleteTokenList(root->next); + } - skipStringCopy: - regfree(®Space); - regfree(®NumberFrac); - regfree(®NumberReal); - regfree(®Symbol); - regfree(®LParenthesis); - regfree(®RParenthesis); - - return result; + free(root); } token *lexLine(char *input) { - int i = 0, n; - n = strlen(input); + regex_t regSpace, regTokenGeneral, regNumberFrac, regNumberReal, + regLParenthesis, regRParenthesis, regSymbol, regQuote; + + regcomp(®Space, "^[[:space:]]*", REG_EXTENDED); + regcomp(®TokenGeneral,"^(\\(|\\)|'|[-,.+/*_\\\\=<>!&?[:alnum:]]+)", + 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 = lex1Token(input, &i); - if ((*new)->type == undefinedToken) + *new = malloc(sizeof(token)); + (*new)->next = NULL; + + if (!regexec(®TokenGeneral, input + i, nmatches, a, 0)) { -/* уколико се у реду нађе токен који је лексички погрешан, штампа се место тог - * токена у реду и бришу се сви токени нађени у реду, функција враћа NULL*/ - fprintf(stderr, "Невалидан токен на месту %d\n", i); - new = &root; - while (*new != NULL) - { - free(root->lexeme); - new = &((*new)->next); - free(root); - root = *new; - } + (*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:]]+$", REG_EXTENDED); + regcomp(®Quote, "^'$", REG_EXTENDED); + regcomp(®LParenthesis, "^\\($", REG_EXTENDED); + regcomp(®RParenthesis, "^\\)$", 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(®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; }