2019-01-06 12:30:07 +01:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <regex.h>
|
|
|
|
|
|
|
|
|
|
#include "lexer.h"
|
|
|
|
|
|
2019-01-06 15:27:54 +01:00
|
|
|
|
token *lex1Token(char *input, int *i);
|
2019-01-06 12:30:07 +01:00
|
|
|
|
/* враћа показивач на једну token структуру, која означава један одређен токен,
|
|
|
|
|
чита улазни стринг од i-тог карактера, и мења i тако да оно затим индексира
|
|
|
|
|
следећи токен или крај стринга*/
|
|
|
|
|
|
|
|
|
|
token *lexLine(char *input)
|
|
|
|
|
{
|
|
|
|
|
int i = 0, n;
|
|
|
|
|
n = strlen(input);
|
|
|
|
|
token *root = NULL, **new;
|
|
|
|
|
new = &root;
|
|
|
|
|
while (i < n)
|
|
|
|
|
{
|
2019-01-06 15:27:54 +01:00
|
|
|
|
*new = lex1Token(input, &i);
|
2019-01-06 12:30:07 +01:00
|
|
|
|
if ((*new)->type == undefined)
|
|
|
|
|
{
|
|
|
|
|
/* уколико се у реду нађе токен који је лексички погрешан, штампа се место тог
|
|
|
|
|
токена у реду и брише се цела листа, функција враћа NULL*/
|
|
|
|
|
fprintf(stderr, "Невалидан токен на месту %d\n", i);
|
|
|
|
|
new = &root;
|
|
|
|
|
while (*new != NULL)
|
|
|
|
|
{
|
|
|
|
|
free(root->lexeme);
|
|
|
|
|
new = &((*new)->next);
|
|
|
|
|
free(root);
|
|
|
|
|
root = *new;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2019-01-06 15:27:54 +01:00
|
|
|
|
new = &((*new)->next);
|
2019-01-06 12:30:07 +01:00
|
|
|
|
}
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
regex_t regNumber, regSymbol, regParenthesis, regSpace;
|
|
|
|
|
|
2019-01-06 15:27:54 +01:00
|
|
|
|
token *lex1Token(char *input, int *i)
|
2019-01-06 12:30:07 +01:00
|
|
|
|
{
|
|
|
|
|
token *result = malloc(sizeof(token));
|
|
|
|
|
result->next = NULL;
|
|
|
|
|
|
2019-01-06 15:27:54 +01:00
|
|
|
|
regcomp(®Space, "^[[:space:]]*", REG_EXTENDED);
|
|
|
|
|
regcomp(®Number, "^[-+]?[[:digit:]]+", REG_EXTENDED);
|
2019-01-06 12:30:07 +01:00
|
|
|
|
regcomp(®Symbol, "^[-+/*]", REG_EXTENDED);
|
|
|
|
|
/* за сада подржава само симболе -, +, * и / */
|
|
|
|
|
regcomp(®Parenthesis, "^[()]", REG_EXTENDED);
|
|
|
|
|
|
|
|
|
|
const int nmatches = 1;
|
|
|
|
|
regmatch_t a[nmatches];
|
|
|
|
|
|
|
|
|
|
regexec(®Space, input + *i, nmatches, a, 0);
|
|
|
|
|
*i += a[0].rm_eo;
|
|
|
|
|
/* помера индекс да би се игнорисали почетни "вајт-спејс" карактери */
|
|
|
|
|
|
|
|
|
|
if (!regexec(®Symbol, input + *i, nmatches, a, 0))
|
|
|
|
|
{
|
|
|
|
|
result->type = symbol;
|
|
|
|
|
}
|
|
|
|
|
else if (!regexec(®Number, input + *i, nmatches, a, 0))
|
|
|
|
|
{
|
|
|
|
|
result->type = number;
|
|
|
|
|
}
|
|
|
|
|
else if (!regexec(®Parenthesis, input + *i, nmatches, a, 0))
|
|
|
|
|
{
|
|
|
|
|
result->type = parenthesis;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result->type = undefined;
|
2019-01-06 15:27:54 +01:00
|
|
|
|
result->lexeme = NULL;
|
2019-01-06 12:30:07 +01:00
|
|
|
|
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;
|
|
|
|
|
/* игнорисање крајњих вајт-спејс карактера */
|
|
|
|
|
|
|
|
|
|
skipStringCopy:
|
|
|
|
|
regfree(®Space);
|
|
|
|
|
regfree(®Number);
|
|
|
|
|
regfree(®Symbol);
|
|
|
|
|
regfree(®Parenthesis);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-01-06 21:13:13 +01:00
|
|
|
|
|
|
|
|
|
void freeLexedLine(token *list)
|
|
|
|
|
{
|
|
|
|
|
if (list == NULL)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
freeLexedLine(list->next);
|
|
|
|
|
if (list->lexeme != NULL)
|
|
|
|
|
{
|
|
|
|
|
free(list->lexeme);
|
|
|
|
|
}
|
|
|
|
|
free(list);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|