197 lines
5.0 KiB
C
197 lines
5.0 KiB
C
#include "ast.h"
|
|
|
|
#include "../status.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
extern struct ast_node_definition null_ast_node;
|
|
extern struct ast_node_definition int_ast_node;
|
|
extern struct ast_node_definition double_ast_node;
|
|
extern struct ast_node_definition word_ast_node;
|
|
extern struct ast_node_definition var_ast_node;
|
|
extern struct ast_node_definition string_ast_node;
|
|
extern struct ast_node_definition fstring_ast_node;
|
|
extern struct ast_node_definition cmdcall_ast_node;
|
|
extern struct ast_node_definition pipeline_ast_node;
|
|
extern struct ast_node_definition redirection_ast_node;
|
|
extern struct ast_node_definition block_ast_node;
|
|
extern struct ast_node_definition stmt_list_ast_node;
|
|
extern struct ast_node_definition func_ast_node;
|
|
extern struct ast_node_definition array_ast_node;
|
|
extern struct ast_node_definition hashtable_ast_node;
|
|
extern struct ast_node_definition hashtable_item_ast_node;
|
|
extern struct ast_node_definition if_ast_node;
|
|
extern struct ast_node_definition if_branch_ast_node;
|
|
extern struct ast_node_definition op_ast_node;
|
|
|
|
static const struct ast_node_definition *ast_node_defintions[] = {
|
|
[AST_NULL] = &null_ast_node,
|
|
[AST_INT] = &int_ast_node,
|
|
[AST_DOUBLE] = &double_ast_node,
|
|
[AST_WORD] = &word_ast_node,
|
|
[AST_VAR] = &var_ast_node,
|
|
[AST_STRING] = &string_ast_node,
|
|
[AST_FSTRING] = &fstring_ast_node,
|
|
[AST_CMDCALL] = &cmdcall_ast_node,
|
|
[AST_PIPELINE] = &pipeline_ast_node,
|
|
[AST_REDIRECTION] = &redirection_ast_node,
|
|
[AST_BLOCK] = &block_ast_node,
|
|
[AST_STMT_LIST] = &stmt_list_ast_node,
|
|
[AST_FUNC] = &func_ast_node,
|
|
[AST_ARRAY] = &array_ast_node,
|
|
[AST_IF] = &if_ast_node,
|
|
[AST_IF_BRANCH] = &if_branch_ast_node,
|
|
[AST_HASHTABLE] = &hashtable_ast_node,
|
|
[AST_HASHTABLE_ITEM] = &hashtable_item_ast_node,
|
|
[AST_OP] = &op_ast_node,
|
|
};
|
|
static const size_t nr_ast_node_definitions
|
|
= sizeof ast_node_defintions / sizeof ast_node_defintions[0];
|
|
|
|
struct ast_node *ast_node_create(enum ast_node_type type)
|
|
{
|
|
assert(type < nr_ast_node_definitions);
|
|
|
|
const struct ast_node_definition *def = ast_node_defintions[type];
|
|
struct ast_node *out = malloc(def->def_node_size);
|
|
if (!out) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(out, 0x0, def->def_node_size);
|
|
|
|
out->n_type = type;
|
|
|
|
return out;
|
|
}
|
|
|
|
void ast_node_destroy(struct ast_node *node)
|
|
{
|
|
assert(node->n_type < nr_ast_node_definitions);
|
|
|
|
struct ast_iterator it = {0};
|
|
ast_iterator_enqueue(&it, node);
|
|
|
|
while (1) {
|
|
node = ast_iterator_peek(&it);
|
|
if (!node) {
|
|
break;
|
|
}
|
|
|
|
const struct ast_node_definition *def
|
|
= ast_node_defintions[node->n_type];
|
|
|
|
if (def->def_cleanup) {
|
|
def->def_cleanup(node);
|
|
}
|
|
|
|
ast_iterator_dequeue(&it);
|
|
free(node);
|
|
}
|
|
}
|
|
|
|
void ast_node_iterate(struct ast_node *node, struct ast_iterator *it)
|
|
{
|
|
ast_iterator_enqueue(it, node);
|
|
}
|
|
|
|
void ast_node_to_string(const struct ast_node *node, fx_bstr *out)
|
|
{
|
|
const struct ast_node_definition *def
|
|
= ast_node_defintions[node->n_type];
|
|
if (def->def_to_string) {
|
|
def->def_to_string(node, out);
|
|
}
|
|
}
|
|
|
|
#define ENUM_STR(x) \
|
|
case x: \
|
|
return #x
|
|
|
|
const char *ast_node_type_to_string(enum ast_node_type type)
|
|
{
|
|
switch (type) {
|
|
ENUM_STR(AST_NONE);
|
|
ENUM_STR(AST_NULL);
|
|
ENUM_STR(AST_STMT_LIST);
|
|
ENUM_STR(AST_INT);
|
|
ENUM_STR(AST_DOUBLE);
|
|
ENUM_STR(AST_WORD);
|
|
ENUM_STR(AST_STRING);
|
|
ENUM_STR(AST_FSTRING);
|
|
ENUM_STR(AST_VAR);
|
|
ENUM_STR(AST_VAR_SPLAT);
|
|
ENUM_STR(AST_FLAG);
|
|
ENUM_STR(AST_CMDCALL);
|
|
ENUM_STR(AST_PIPELINE);
|
|
ENUM_STR(AST_REDIRECTION);
|
|
ENUM_STR(AST_BLOCK);
|
|
ENUM_STR(AST_FUNC);
|
|
ENUM_STR(AST_IF);
|
|
ENUM_STR(AST_IF_BRANCH);
|
|
ENUM_STR(AST_OP);
|
|
ENUM_STR(AST_ARRAY);
|
|
ENUM_STR(AST_HASHTABLE);
|
|
ENUM_STR(AST_HASHTABLE_ITEM);
|
|
default:
|
|
return "<unknown>";
|
|
}
|
|
}
|
|
|
|
struct ast_node *ast_iterator_peek(struct ast_iterator *it)
|
|
{
|
|
fx_queue_entry *cur = fx_queue_first(&it->it_queue);
|
|
if (!cur) {
|
|
return NULL;
|
|
}
|
|
|
|
return fx_unbox(struct ast_node, cur, n_it.e_entry);
|
|
}
|
|
|
|
struct ast_node *ast_iterator_dequeue(struct ast_iterator *it)
|
|
{
|
|
fx_queue_entry *cur = fx_queue_first(&it->it_queue);
|
|
if (!cur) {
|
|
return NULL;
|
|
}
|
|
|
|
struct ast_node *node = fx_unbox(struct ast_node, cur, n_it.e_entry);
|
|
const struct ast_node_definition *def
|
|
= ast_node_defintions[node->n_type];
|
|
|
|
it->it_insert_after = cur;
|
|
if (def->def_collect_children) {
|
|
def->def_collect_children(node, it);
|
|
}
|
|
|
|
fx_queue_pop_front(&it->it_queue);
|
|
return fx_unbox(struct ast_node, cur, n_it.e_entry);
|
|
}
|
|
|
|
void ast_iterator_enqueue(struct ast_iterator *it, struct ast_node *node)
|
|
{
|
|
unsigned long new_depth = 0;
|
|
|
|
fx_queue_entry *cur = fx_queue_first(&it->it_queue);
|
|
if (cur) {
|
|
struct ast_node *cur_node
|
|
= fx_unbox(struct ast_node, cur, n_it.e_entry);
|
|
new_depth = cur_node->n_it.e_depth + 1;
|
|
}
|
|
|
|
node->n_it.e_depth = new_depth;
|
|
|
|
if (!it->it_insert_after) {
|
|
fx_queue_push_back(&it->it_queue, &node->n_it.e_entry);
|
|
return;
|
|
}
|
|
|
|
fx_queue_insert_after(
|
|
&it->it_queue,
|
|
&node->n_it.e_entry,
|
|
it->it_insert_after);
|
|
it->it_insert_after = &node->n_it.e_entry;
|
|
}
|