99 lines
2.7 KiB
C
99 lines
2.7 KiB
C
#include <compiler/fzl_parser.h>
|
|
#include <compiler/internals/parser.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
// Parse postfix expressions (parens, index access, dots)
|
|
fzl_node_t *pa_postfix(fzl_parser_t *parser)
|
|
{
|
|
if (!parser)
|
|
return NULL;
|
|
|
|
fzl_node_t *left = pa_primary(parser);
|
|
|
|
if (!left)
|
|
return NULL;
|
|
|
|
if (is(parser, FZL_TOKTYPE_LPAREN) || is(parser, FZL_TOKTYPE_DOT))
|
|
{
|
|
while (is(parser, FZL_TOKTYPE_LPAREN) || is(parser, FZL_TOKTYPE_DOT))
|
|
{
|
|
fzl_token_t *post = consume(parser);
|
|
|
|
if (post->type == FZL_TOKTYPE_LPAREN)
|
|
{
|
|
size_t args_capacity = 2;
|
|
size_t args_count = 0;
|
|
fzl_node_t **args = malloc(args_capacity * sizeof(fzl_node_t *));
|
|
|
|
while (!is(parser, FZL_TOKTYPE_RPAREN))
|
|
{
|
|
fzl_node_t *arg = pa_expression(parser);
|
|
if (!arg)
|
|
{
|
|
for (size_t i = 0; i < args_count; i++)
|
|
fzl_freeast(args[i]);
|
|
free(args);
|
|
fzl_freeast(left);
|
|
return NULL;
|
|
}
|
|
|
|
if (args_capacity <= args_count)
|
|
{
|
|
args_capacity *= 2;
|
|
args = realloc(args, args_capacity * sizeof(fzl_node_t *));
|
|
}
|
|
|
|
args[args_count] = arg;
|
|
args_count++;
|
|
|
|
if (is(parser, FZL_TOKTYPE_COMMA))
|
|
consume(parser);
|
|
}
|
|
|
|
fzl_token_t *rparen = consume(parser);
|
|
if (!rparen || rparen->type != FZL_TOKTYPE_RPAREN)
|
|
{
|
|
for (size_t i = 0; i < args_count; i++)
|
|
fzl_freeast(args[i]);
|
|
free(args);
|
|
fzl_freeast(left);
|
|
snprintf(plast_err, sizeof(plast_err),
|
|
"'%s': expected ')' after argument list at %ld:%ld",
|
|
last_known_tok->filename, last_known_tok->ln,
|
|
last_known_tok->cn);
|
|
return NULL;
|
|
}
|
|
|
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CALL, left->token);
|
|
node->call.callee = left;
|
|
node->call.args = args;
|
|
node->call.args_count = args_count;
|
|
|
|
left = node;
|
|
}
|
|
else if (post->type == FZL_TOKTYPE_DOT)
|
|
{
|
|
if (!is(parser, FZL_TOKTYPE_NAME))
|
|
{
|
|
fzl_freeast(left);
|
|
snprintf(plast_err, sizeof(plast_err),
|
|
"'%s': expected name after '.' at %ld:%ld",
|
|
last_known_tok->filename, last_known_tok->ln,
|
|
last_known_tok->cn);
|
|
return NULL;
|
|
}
|
|
|
|
fzl_token_t *name = consume(parser);
|
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FIELD, name);
|
|
node->memb.parent = left;
|
|
node->memb.field = fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
|
|
|
left = node;
|
|
}
|
|
}
|
|
}
|
|
|
|
return left;
|
|
}
|