Files
fz-lang/src/compiler/fzl_reader.c
T
samsonium 1db985ecb5 feat+fix: make compiler STRONGAAA
- FEAT: add source code length field in `fzl_reader_t` struct
- FIX: check name, lpair (lparen) and rpair (rparen) when lexing call
- FIX: check string literal termination
- FIX: increment position even on empty string to prevent infinite
lexing loop
- FIX: add string terminator in `fzl_mktoken` when allocating space for
string value
- FIX: add check for errors in recursevly called `walk`
- FIX: change source code holder from stack-stored `char[8192]` to
dynamically allocated with actual file size holder
- FIX: correct constant hasing util to hash actual string value instead
of link
2026-10-10 21:03:23 +03:00

193 lines
4.0 KiB
C

#include <compiler/fzl_reader.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Last error from reader
static char last_err[256] = {0};
fzl_reader_t *fzl_mkreader(char *source)
{
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->source = source;
reader->size = strlen(source);
reader->position = 0;
reader->at_end = true;
return reader;
}
// --- Read zone ---
// Try parse name
fzl_token_t *parse_name(fzl_reader_t *reader)
{
size_t lpos = reader->position;
size_t size = 0;
do
{
lpos++;
size++;
} while ((reader->source[lpos] >= 'A' && reader->source[lpos] <= 'Z') ||
(reader->source[lpos] >= 'a' && reader->source[lpos] <= 'z'));
char *value = malloc(size);
memcpy(value, reader->source + reader->position, size);
size_t start = reader->position;
reader->position += size;
fzl_token_t *tok =
fzl_mktoken(FZL_TOKTYPE_NAME, start, reader->position - 1, value, size);
free(value);
return tok;
}
// Try parse string literal
fzl_token_t *parse_string_literal(fzl_reader_t *reader)
{
size_t lpos = reader->position;
size_t size = 0;
if (reader->source[lpos] != '\'' && reader->source[lpos] != '"')
return NULL;
char open_symbol = reader->source[lpos];
char close_symbol = '\0';
do
{
lpos++;
size++;
if (reader->source[lpos] == open_symbol)
close_symbol = open_symbol;
} while (reader->source[lpos] != open_symbol && lpos < reader->size);
size++;
if (close_symbol != open_symbol)
return NULL;
if (size == 2)
{
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, reader->position,
reader->position + 1, "", 0);
reader->position += 2;
return tok;
}
char *value = malloc(size - 2);
memcpy(value, reader->source + reader->position + 1, size - 2);
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, reader->position,
lpos, value, size - 2);
free(value);
reader->position += size;
return tok;
}
int fzl_read(fzl_reader_t *reader)
{
if (reader->position >= reader->size)
return 0;
do
{
size_t p = reader->position;
fzl_token_t *token;
char curr = reader->source[p];
if (curr == '\n' || curr == ' ' || curr == '\r')
{
reader->position++;
continue;
}
if (curr == '\'' || curr == '"')
token = parse_string_literal(reader);
else if (curr == '(')
{
token = fzl_mktoken(FZL_TOKTYPE_LPAIR, p, p, NULL, 0);
reader->position++;
}
else if (curr == ')')
{
token = fzl_mktoken(FZL_TOKTYPE_RPAIR, p, p, NULL, 0);
reader->position++;
}
else if (curr >= 'A' && curr <= 'Z' || curr >= 'a' && curr <= 'z')
token = parse_name(reader);
else
{
sprintf(last_err, "undefined token '%c'", curr);
return -1;
}
if (!token)
{
size_t line = 1, linepos = 1;
for (size_t i = 0; i < p; i++)
{
char sym = reader->source[i];
if (sym == '\n')
{
linepos = 1;
line++;
}
else
linepos++;
}
sprintf(last_err, "cannot parse token (%ld:%ld)", line, linepos);
return -1;
}
fzl_reader_ll_t *tok_node = malloc(sizeof(fzl_reader_ll_t));
tok_node->token = token;
reader->last->next = tok_node;
reader->last = tok_node;
} while (reader->position < reader->size);
reader->at_end = true;
return 0;
}
// --- Read zone end ---
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);
}