cirilisp/lexer.c

121 lines
3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
}