roza/lib/lexer.c

96 lines
1.9 KiB
C
Raw Normal View History

2023-12-09 17:24:41 +00:00
#include "lexer.h"
#include "lib/commons.h"
void lexer_init(lexer_t* lexer, char const* source, err_t* err)
{
assert(lexer);
lexer->source = strdup(source);
lexer->cursor = 0;
lexer->err = err;
lexer->line = 1;
}
void lexer_free(lexer_t* lexer)
{
assert(lexer);
free(lexer->source);
lexer->source = NULL;
}
node_t* lexer_try_new_next(lexer_t* lexer)
{
assert(lexer);
size_t len = strlen(lexer->source);
// skip spaces
{
while (lexer->cursor < len
&& isspace(lexer->source[lexer->cursor]))
{
if (lexer->source[lexer->cursor] == '\n')
{
lexer->line++;
}
lexer->cursor++;
}
}
// scan num
{
size_t cursor = lexer->cursor;
str_t res_str;
str_init(&res_str);
if (cursor < len && lexer->source[cursor] == '-')
{
str_push(&res_str, lexer->source[cursor]);
cursor++;
}
while (cursor < len
&& isdigit(lexer->source[cursor]))
{
str_push(&res_str, lexer->source[cursor]);
cursor += 1;
}
if (cursor < len && lexer->source[cursor] == '.')
{
str_push(&res_str, lexer->source[cursor]);
cursor++;
while (cursor < len
&& isdigit(lexer->source[cursor]))
{
str_push(&res_str, lexer->source[cursor]);
cursor += 1;
}
}
if (res_str.size > 0
&& (cursor >= len || isspace(lexer->source[cursor])))
{
node_t* tok = malloc(sizeof(node_t));
node_init(tok, NODE_NUM, res_str.data, lexer->line);
str_free(&res_str);
lexer->cursor = cursor;
return tok;
}
str_free(&res_str);
}
if (lexer->cursor < len && lexer->err)
{
size_t const SZ = RZ_STR_LIMIT;
char msg[SZ];
snprintf(msg, SZ, "unexpected symbol '%c'", lexer->source[lexer->cursor]);
err_error(lexer->err, msg, lexer->line);
}
return NULL;
}