Уведен лексер, још увек нестабилан и минималан
This commit is contained in:
parent
7cff23f9ca
commit
8d89aa622a
4
Makefile
4
Makefile
|
@ -13,7 +13,7 @@ LDFLAGS = -lm -lc
|
||||||
|
|
||||||
CC = cc
|
CC = cc
|
||||||
|
|
||||||
SRC = cirilisp.c util.c
|
SRC = cirilisp.c util.c lexer.c
|
||||||
OBJ = $(SRC:.c=.o)
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
all: cirilisp
|
all: cirilisp
|
||||||
|
@ -21,7 +21,7 @@ all: cirilisp
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) -c $(CFLAGS) $<
|
$(CC) -c $(CFLAGS) $<
|
||||||
|
|
||||||
$(OBJ): util.h
|
$(OBJ): util.h lexer.h
|
||||||
|
|
||||||
cirilisp: $(OBJ)
|
cirilisp: $(OBJ)
|
||||||
$(CC) -o $@ $(OBJ) $(LDFLAGS)
|
$(CC) -o $@ $(OBJ) $(LDFLAGS)
|
||||||
|
|
32
cirilisp.c
32
cirilisp.c
|
@ -3,32 +3,38 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "lexer.h"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// Омогућава библиотекама коришћеним у интерпретеру да протумаче
|
/* Омогућава библиотекама коришћеним у интерпретеру да протумаче српску ћирилицу */
|
||||||
// српску ћирилицу
|
if (setlocale(LC_ALL, "sr_RS.utf8") == NULL)
|
||||||
// struct lconv *loc;
|
{
|
||||||
setlocale(LC_ALL, "sr_RS.utf8");
|
fprintf(stderr, "locale couldn't be set to \"sr_RS.utf8\", check if you've enabled it on your system\n");
|
||||||
// loc = localeconv();
|
exit(0);
|
||||||
|
}
|
||||||
// Бојлерплејт обавештења о окружењу
|
|
||||||
puts("Прост РЕПЛ:");
|
|
||||||
puts("Притисните ctrl+c да бисте изашли\n");
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
char *input = readline("k> ");
|
char *input = readline("Л> ");
|
||||||
if (input == NULL)
|
if (input == NULL)
|
||||||
{
|
{
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
printf("Крај улазног тока.\n");
|
||||||
|
// Превод
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("НАПИСАЛИ СТЕ: %s\n", input);
|
token *tokenList, *current;
|
||||||
|
current = tokenList = lexLine(input);
|
||||||
|
int i = 0;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
printf("Токен бр. %d: \"%s\", тип:%s\n", i,
|
||||||
|
current->lexeme, current->type == number ? "number" : (current->type == symbol
|
||||||
|
? "symbol" : "parenthesis"));
|
||||||
|
}
|
||||||
|
|
||||||
free(input);
|
free(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
95
lexer.c
Normal file
95
lexer.c
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#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);
|
||||||
|
new = &((*new)->next);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
regex_t regNumber, regSymbol, regParenthesis, regSpace;
|
||||||
|
|
||||||
|
token *lex1token(char *input, int *i)
|
||||||
|
{
|
||||||
|
token *result = malloc(sizeof(token));
|
||||||
|
result->next = NULL;
|
||||||
|
|
||||||
|
regcomp(®Space, "^[:space:]*", REG_EXTENDED);
|
||||||
|
regcomp(®Number, "^[-+]?[:digit:]+", REG_EXTENDED);
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
20
lexer.h
Normal file
20
lexer.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
undefined,
|
||||||
|
number,
|
||||||
|
symbol,
|
||||||
|
parenthesis
|
||||||
|
} tokenType ;
|
||||||
|
|
||||||
|
typedef struct _Token
|
||||||
|
{
|
||||||
|
tokenType type;
|
||||||
|
char *lexeme;
|
||||||
|
struct _Token *next;
|
||||||
|
} token;
|
||||||
|
|
||||||
|
/* функција lexLine као аргумент добија ред са стандардног улаза, а као излаз
|
||||||
|
враћа лексичке елементе у повезаној листи */
|
||||||
|
token *lexLine(char *input);
|
Loading…
Reference in a new issue