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
+86
View File
@@ -151,6 +151,91 @@ fzl_node_t *parse_primary(fzl_parser_t *parser)
fzl_token_t *tok = consume(parser);
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
}
else if (is(parser, FZL_TOKTYPE_STR_FORMAT_START))
{
consume(parser);
size_t remainder = 2;
size_t count = 0;
fzl_node_t **entries = malloc(remainder * sizeof(fzl_node_t *));
if (!entries)
{
snprintf(plast_err, sizeof(plast_err), "out of memory");
return NULL;
}
while (peek(parser) && peek(parser)->type != FZL_TOKTYPE_STR_FORMAT_END)
{
if (remainder <= count)
{
remainder *= 2;
entries = realloc(entries, remainder * sizeof(fzl_node_t *));
if (!entries)
{
snprintf(plast_err, sizeof(plast_err), "out of memory");
return NULL;
}
}
if (is(parser, FZL_TOKTYPE_STR_FORMAT_END))
break;
fzl_node_t *expr = parse_expression(parser);
if (!expr)
{
for (size_t i = 0; i < count; i++)
fzl_freeast(entries[i]);
free(entries);
return NULL;
}
entries[count++] = expr;
}
fzl_token_t *end = consume(parser);
if (end->type != FZL_TOKTYPE_STR_FORMAT_END)
{
snprintf(plast_err, sizeof(plast_err),
"'%s':%zu:%zu => unterminated format string",
last_known_tok->filename, last_known_tok->ln,
last_known_tok->cn);
for (size_t i = 0; i < count; i++)
fzl_freeast(entries[i]);
free(entries);
}
if (count < 1)
{
snprintf(plast_err, sizeof(plast_err),
"'%s':%zu:%zu => do you really need empty format string?",
last_known_tok->filename, last_known_tok->ln,
last_known_tok->cn);
for (size_t i = 0; i < count; i++)
fzl_freeast(entries[i]);
free(entries);
return NULL;
}
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FMT_STRING, entries[0]->token);
if (!node)
{
snprintf(plast_err, sizeof(plast_err), "out of memory");
for (size_t i = 0; i < count; i++)
fzl_freeast(entries[i]);
free(entries);
return NULL;
}
node->list.entries = entries;
node->list.entry_count = count;
return node;
}
else if (is(parser, FZL_TOKTYPE_LPAREN))
{
consume(parser);
@@ -1308,6 +1393,7 @@ void fzl_freeast(fzl_node_t *root)
case FZL_NODETYPE_LITERAL:
break;
case FZL_NODETYPE_FMT_STRING:
case FZL_NODETYPE_BLOCK:
if (root->list.entries)
{