feat: enhance compiler

- Add comments and test for it
- Add semicolon as required end of some expressions
- Add new arguments parser
- Add multi-file compilation
- Add colors in output
This commit is contained in:
samsonium
2026-10-15 17:20:43 +03:00
parent 1035b9193c
commit 69b2253c34
22 changed files with 739 additions and 327 deletions
+86 -37
View File
@@ -1,4 +1,5 @@
#include "compiler/fzl_token.h"
#include "compiler/utils/fzl_linked.h"
#include <compiler/fzl_reader.h>
#include <stdbool.h>
#include <stddef.h>
@@ -9,7 +10,7 @@
// Last error from reader
static char last_err[256] = {0};
fzl_reader_t *fzl_mkreader(char *source)
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;
@@ -18,11 +19,10 @@ fzl_reader_t *fzl_mkreader(char *source)
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->linked = linked;
reader->source = linked->source;
reader->size = linked->total_sz;
reader->position = 0;
reader->line_n = 1;
reader->line_start = 0;
return reader;
}
@@ -30,21 +30,12 @@ fzl_reader_t *fzl_mkreader(char *source)
// --- Read zone ---
// Move cursor forward
// @deprecated
static size_t move(fzl_reader_t *reader, size_t len)
{
if (!reader)
return 0;
char *src = reader->source;
for (size_t i = 0; i < len; i++)
{
if (src[reader->position + i] == '\n')
{
reader->line_n++;
reader->line_start = reader->position + i + 1;
}
}
return reader->position += len;
}
@@ -71,17 +62,24 @@ fzl_token_t *parse_name(fzl_reader_t *reader)
move(reader, size);
fzl_token_t *tok;
size_t line = reader->line_n;
size_t pos = start - reader->line_start;
fzl_file_loc l;
bool ok = fzl_linked_getpos(reader->linked, start, &l);
if (!ok)
{
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
return NULL;
}
if (strcmp(value, "return") == 0)
tok = fzl_mktoken(FZL_TOKTYPE_RETURN, line, pos, value, size);
tok =
fzl_mktoken(FZL_TOKTYPE_RETURN, l.line, l.col, value, size, l.filename);
else if (strcmp(value, "if") == 0)
tok = fzl_mktoken(FZL_TOKTYPE_IF, line, pos, value, size);
tok = fzl_mktoken(FZL_TOKTYPE_IF, l.line, l.col, value, size, l.filename);
else if (strcmp(value, "else") == 0)
tok = fzl_mktoken(FZL_TOKTYPE_ELSE, line, pos, value, size);
tok = fzl_mktoken(FZL_TOKTYPE_ELSE, l.line, l.col, value, size, l.filename);
else if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0)
tok = fzl_mktoken(FZL_TOKTYPE_BOOL_LITERAL, line, pos, value, size);
tok = fzl_mktoken(FZL_TOKTYPE_BOOL_LITERAL, l.line, l.col, value, size,
l.filename);
else if (strcmp(value, "str") == 0 || strcmp(value, "char") == 0 ||
strcmp(value, "bool") == 0 || strcmp(value, "uint") == 0 ||
strcmp(value, "int") == 0 || strcmp(value, "i8") == 0 ||
@@ -89,9 +87,9 @@ fzl_token_t *parse_name(fzl_reader_t *reader)
strcmp(value, "i64") == 0 || strcmp(value, "u8") == 0 ||
strcmp(value, "u16") == 0 || strcmp(value, "u32") == 0 ||
strcmp(value, "u64") == 0)
tok = fzl_mktoken(FZL_TOKTYPE_TYPE, line, pos, value, size);
tok = fzl_mktoken(FZL_TOKTYPE_TYPE, l.line, l.col, value, size, l.filename);
else
tok = fzl_mktoken(FZL_TOKTYPE_NAME, line, pos, value, size);
tok = fzl_mktoken(FZL_TOKTYPE_NAME, l.line, l.col, value, size, l.filename);
free(value);
return tok;
@@ -120,26 +118,33 @@ fzl_token_t *parse_string_literal(fzl_reader_t *reader)
} while (reader->source[lpos] != open_symbol && lpos < reader->size);
size++;
fzl_file_loc l;
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
if (!ok)
{
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
return NULL;
}
if (close_symbol != open_symbol)
{
snprintf(last_err, sizeof(last_err), "unterminated string at %ld:%ld",
reader->line_n, reader->position - reader->line_start);
snprintf(last_err, sizeof(last_err), "'%s': unterminated string at %ld:%ld",
l.filename, l.line, l.col);
return NULL;
}
if (size == 2)
{
fzl_token_t *tok =
fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, reader->line_n,
reader->position - reader->line_start, "", 0);
fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, "", 0, l.filename);
move(reader, 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->line_n,
lpos - reader->line_start, value, size - 2);
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
size - 2, l.filename);
free(value);
move(reader, size);
@@ -166,8 +171,16 @@ fzl_token_t *parse_number(fzl_reader_t *reader)
memcpy(value, reader->source + reader->position, size);
value[size] = '\0';
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NUM_LITERAL, reader->line_n,
lpos - reader->line_start, value, size);
fzl_file_loc l;
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
if (!ok)
{
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
return NULL;
}
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NUM_LITERAL, l.line, l.col, value,
size, l.filename);
free(value);
if (!tok)
@@ -181,14 +194,31 @@ fzl_token_t *parse_number(fzl_reader_t *reader)
fzl_token_t *add_single(fzl_reader_t *reader, fzl_toktype_t type)
{
size_t p = move(reader, 1);
return fzl_mktoken(type, reader->line_n, p - reader->line_start, NULL, 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 NULL;
}
return fzl_mktoken(type, l.line, l.col, NULL, 0, l.filename);
}
// Add double-char token
fzl_token_t *add_double(fzl_reader_t *reader, fzl_toktype_t type)
{
size_t p = move(reader, 2);
return fzl_mktoken(type, reader->line_n, p - reader->line_start, NULL, 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 NULL;
}
return fzl_mktoken(type, l.line, l.col, NULL, 0, l.filename);
}
// Skip symbols until '\n' or EOF
void skip_comment(fzl_reader_t *reader)
@@ -277,16 +307,35 @@ int fzl_read(fzl_reader_t *reader)
token = parse_number(reader);
else
{
sprintf(last_err, "undefined token '%c' at %ld:%ld", curr, reader->line_n,
p - reader->line_start);
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])
sprintf(last_err, "cannot parse token at %ld:%ld", reader->line_n,
p - reader->line_start);
{
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;
}