Files
fz-lang/src/compiler/fzl_reader.c
T

190 lines
5.2 KiB
C

#include <compiler/fzl_reader.h>
#include <compiler/fzl_token.h>
#include <compiler/internals/reader.h>
#include <compiler/utils/fzl_linked.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Last error from reader
char last_err[256];
fzl_reader_t *fzl_mkreader(fzl_linked_t *linked)
{
fzl_reader_ll_t *first_node = malloc(sizeof(fzl_reader_ll_t));
first_node->token = NULL;
first_node->next = NULL;
fzl_reader_t *reader = malloc(sizeof(fzl_reader_t));
reader->first = first_node;
reader->last = first_node;
reader->linked = linked;
reader->source = linked->source;
reader->size = linked->total_sz;
reader->position = 0;
memset(last_err, 0, sizeof(last_err));
return reader;
}
int fzl_read(fzl_reader_t *reader)
{
if (reader->position >= reader->size)
return 0;
bool is_format_str = false;
do
{
size_t p = reader->position;
fzl_token_t *token;
char curr = reader->source[p];
if (is_format_str)
{
token = rd_fmtstr(reader);
if (token && token->type == FZL_TOKTYPE_STR_FORMAT_END)
is_format_str = false;
}
else if (curr == '\n' || curr == ' ' || curr == '\r')
{
move(reader, 1);
continue;
}
else if (curr == '\'' || curr == '"')
token = rd_string_literal(reader);
else if (curr == '/' && reader->source[p + 1] == '/')
{
rd_comment(reader);
continue;
}
else if (curr == '=' && reader->source[p + 1] == '=')
token = rd_double(reader, FZL_TOKTYPE_EQEQ);
else if (curr == '>' && reader->source[p + 1] == '=')
token = rd_double(reader, FZL_TOKTYPE_REQ);
else if (curr == '<' && reader->source[p + 1] == '=')
token = rd_double(reader, FZL_TOKTYPE_LEQ);
else if (curr == '!' && reader->source[p + 1] == '=')
token = rd_double(reader, FZL_TOKTYPE_NEQ);
else if (curr == '|' && reader->source[p + 1] == '|')
token = rd_double(reader, FZL_TOKTYPE_DVBAR);
else if (curr == '&' && reader->source[p + 1] == '&')
token = rd_double(reader, FZL_TOKTYPE_DAMPERSAND);
else if (curr == '>')
token = rd_single(reader, FZL_TOKTYPE_RANGLE);
else if (curr == '<')
token = rd_single(reader, FZL_TOKTYPE_LANGLE);
else if (curr == '!')
token = rd_single(reader, FZL_TOKTYPE_NOT);
else if (curr == ';')
token = rd_single(reader, FZL_TOKTYPE_SEMICOLON);
else if (curr == '{')
token = rd_single(reader, FZL_TOKTYPE_LBRACE);
else if (curr == '}')
token = rd_single(reader, FZL_TOKTYPE_RBRACE);
else if (curr == '(')
token = rd_single(reader, FZL_TOKTYPE_LPAREN);
else if (curr == ')')
token = rd_single(reader, FZL_TOKTYPE_RPAREN);
else if (curr == ',')
token = rd_single(reader, FZL_TOKTYPE_COMMA);
else if (curr == '.')
token = rd_single(reader, FZL_TOKTYPE_DOT);
else if (curr == '*')
token = rd_single(reader, FZL_TOKTYPE_STAR);
else if (curr == '/')
token = rd_single(reader, FZL_TOKTYPE_SLASH);
else if (curr == '+')
token = rd_single(reader, FZL_TOKTYPE_PLUS);
else if (curr == '-')
token = rd_single(reader, FZL_TOKTYPE_MINUS);
else if (curr == '^')
token = rd_single(reader, FZL_TOKTYPE_CARET);
else if (curr == '%')
token = rd_single(reader, FZL_TOKTYPE_PERCENT);
else if (curr == '=')
token = rd_single(reader, FZL_TOKTYPE_EQ);
else if (curr == '$' && reader->source[p + 1] == '"')
{
move(reader, 2);
is_format_str = true;
token = fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_START, 0, 0, NULL, 0, "");
}
else if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') ||
curr == '_')
token = rd_name(reader);
else if (curr >= '0' && curr <= '9')
token = rd_number(reader);
else
{
fzl_file_loc l;
bool ok = fzl_linked_getpos(reader->linked, p, &l);
if (!ok)
{
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
return -1;
}
sprintf(last_err, "'%s': undefined token '%c' at %ld:%ld", l.filename,
curr, l.line, l.col);
return -1;
}
if (!token)
{
if (!last_err[0])
{
fzl_file_loc l;
bool ok = fzl_linked_getpos(reader->linked, p, &l);
if (!ok)
{
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
return -1;
}
sprintf(last_err, "'%s': cannot parse token at %ld:%ld", l.filename,
l.line, l.col);
}
return -1;
}
fzl_reader_ll_t *tok_node = malloc(sizeof(fzl_reader_ll_t));
tok_node->next = NULL;
tok_node->token = token;
reader->last->next = tok_node;
reader->last = tok_node;
} while (reader->position < reader->size);
return 0;
}
char *fzl_reader_geterror() { return last_err; }
void free_node_and_next(fzl_reader_ll_t *node)
{
if (!node)
return;
if (node->next)
free_node_and_next(node->next);
if (node->token)
fzl_freetoken(node->token);
free(node);
}
void fzl_freereader(fzl_reader_t *reader)
{
if (!reader)
return;
if (reader->first)
free_node_and_next(reader->first);
free(reader);
}