Files
fz-lang/src/compiler/parser/pa_primary.c
T

165 lines
4.4 KiB
C

#include <compiler/fzl_parser.h>
#include <compiler/internals/parser.h>
#include <stdio.h>
#include <stdlib.h>
// Parse primary
fzl_node_t *pa_primary(fzl_parser_t *parser)
{
if (!parser || !peek(parser))
return NULL;
if (is(parser, FZL_TOKTYPE_STR_LITERAL) ||
is(parser, FZL_TOKTYPE_NUM_LITERAL) ||
is(parser, FZL_TOKTYPE_BOOL_LITERAL) ||
is(parser, FZL_TOKTYPE_NULL_LITERAL))
{
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 (is(parser, FZL_TOKTYPE_STR_FORMAT_END))
break;
if (remainder <= count)
{
remainder *= 2;
fzl_node_t **newentries =
realloc(entries, remainder * sizeof(fzl_node_t *));
if (!newentries)
{
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;
}
entries = newentries;
}
fzl_node_t *expr = pa_expression(parser);
if (expr == NULL)
{
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);
fzl_node_t *node = pa_expression(parser);
if (!is(parser, FZL_TOKTYPE_RPAREN))
{
snprintf(plast_err, sizeof(plast_err), "'%s': expected ')' at %ld:%ld",
last_known_tok->filename, last_known_tok->ln,
last_known_tok->cn);
fzl_freeast(node);
return NULL;
}
consume(parser);
return node;
}
else if (is(parser, FZL_TOKTYPE_NAME))
{
fzl_token_t *name = consume(parser);
if (!is(parser, FZL_TOKTYPE_NAME))
return fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
fzl_token_t *realname = consume(parser); // :D
fzl_node_t *decl = fzl_mknode(FZL_NODETYPE_DECLARATION, name);
decl->var.type = name;
decl->var.identifier = fzl_mknode(FZL_NODETYPE_IDENTIFIER, realname);
return decl;
}
else if (is(parser, FZL_TOKTYPE_TYPE))
{
fzl_token_t *type = consume(parser);
fzl_token_t *name = consume(parser);
if (!name || name->type != FZL_TOKTYPE_NAME)
{
snprintf(plast_err, sizeof(plast_err),
"'%s': expected name after type at %ld:%ld",
last_known_tok->filename, last_known_tok->ln,
last_known_tok->cn);
return NULL;
}
fzl_node_t *decl = fzl_mknode(FZL_NODETYPE_DECLARATION, type);
decl->var.type = type;
decl->var.identifier = fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
return decl;
}
if (!plast_err[0])
snprintf(plast_err, sizeof(plast_err),
"'%s': expected expression at %ld:%ld", last_known_tok->filename,
last_known_tok->ln, last_known_tok->cn);
return NULL;
}