feat: implement format strings

This commit is contained in:
samsonium
2026-10-28 17:57:18 +03:00
parent ea28c470d2
commit e11089c90f
11 changed files with 354 additions and 7 deletions
+85 -1
View File
@@ -251,11 +251,83 @@ void skip_comment(fzl_reader_t *reader)
}
}
// Parse string format
fzl_token_t *parse_fmtstring_part(fzl_reader_t *reader)
{
size_t p = reader->position;
char *src = reader->source;
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 (src[p] == '{')
{
move(reader, 1);
fzl_token_t *id = parse_name(reader);
if (id == NULL || src[reader->position] != '}')
{
snprintf(last_err, sizeof(last_err),
"'%s':%zu:%zu => failed to parse format string", l.filename,
l.line, l.col);
fzl_freetoken(id);
return NULL;
}
move(reader, 1);
return id;
}
if (src[p] == '"')
{
move(reader, 1);
return fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_END, l.line, l.col, NULL, 0,
l.filename);
}
size_t size = 0;
size_t lpos = p;
do
{
if (src[lpos + 1] == '"')
break;
size++;
lpos++;
} while (lpos < reader->size && reader->source[lpos] != '{' &&
reader->source[lpos] != '"');
ok = fzl_linked_getpos(reader->linked, reader->position, &l);
if (!ok)
{
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
return NULL;
}
char *value = malloc(size);
memcpy(value, reader->source + reader->position, size);
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
size, l.filename);
free(value);
move(reader, size);
return tok;
}
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;
@@ -268,7 +340,13 @@ int fzl_read(fzl_reader_t *reader)
continue;
}
if (curr == '\'' || curr == '"')
if (is_format_str)
{
token = parse_fmtstring_part(reader);
if (token && token->type == FZL_TOKTYPE_STR_FORMAT_END)
is_format_str = false;
}
else if (curr == '\'' || curr == '"')
token = parse_string_literal(reader);
else if (curr == '/' && reader->source[p + 1] == '/')
{
@@ -321,6 +399,12 @@ int fzl_read(fzl_reader_t *reader)
token = add_single(reader, FZL_TOKTYPE_PERCENT);
else if (curr == '=')
token = add_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 = parse_name(reader);