96 lines
1.9 KiB
C
96 lines
1.9 KiB
C
#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;
|
|
}
|