cirilisp/lexer.c

121 lines
3 KiB
C
Raw Normal View History

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