mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-25 08:53:55 +00:00
232 lines
11 KiB
C
232 lines
11 KiB
C
#include <string.h>
|
|
#include "../lib/mlrutil.h"
|
|
#include "ex_ast.h"
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_t* ex_ast_alloc() {
|
|
ex_ast_t* past = mlr_malloc_or_die(sizeof(ex_ast_t));
|
|
past->proot = NULL;
|
|
return past;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_alloc(char* text, ex_ast_node_type_t type) {
|
|
ex_ast_node_t* pnode = (ex_ast_node_t*)mlr_malloc_or_die(
|
|
sizeof(ex_ast_node_t));
|
|
pnode->text = mlr_strdup_or_die(text);
|
|
pnode->type = type;
|
|
pnode->pchildren = NULL;
|
|
return pnode;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_copy(ex_ast_node_t* pother) {
|
|
ex_ast_node_t* pnode = ex_ast_node_alloc(pother->text, pother->type);
|
|
return pnode;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_tree_copy(ex_ast_node_t* pold) {
|
|
ex_ast_node_t* pnew = ex_ast_node_copy(pold);
|
|
if (pold->pchildren != NULL) {
|
|
pnew->pchildren = sllv_alloc();
|
|
for (sllve_t* pe = pold->pchildren->phead; pe != NULL; pe = pe->pnext) {
|
|
ex_ast_node_t* pchild = pe->pvvalue;
|
|
sllv_append(pnew->pchildren, ex_ast_tree_copy(pchild));
|
|
}
|
|
}
|
|
return pnew;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_alloc_zary(char* text, ex_ast_node_type_t type)
|
|
{
|
|
ex_ast_node_t* pnode = ex_ast_node_alloc(text, type);
|
|
pnode->pchildren = sllv_alloc();
|
|
return pnode;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_alloc_unary(char* text, ex_ast_node_type_t type,
|
|
ex_ast_node_t* pa)
|
|
{
|
|
ex_ast_node_t* pnode = ex_ast_node_alloc(text, type);
|
|
pnode->pchildren = sllv_alloc();
|
|
sllv_append(pnode->pchildren, pa);
|
|
return pnode;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_alloc_binary(char* text, ex_ast_node_type_t type,
|
|
ex_ast_node_t* pa, ex_ast_node_t* pb)
|
|
{
|
|
ex_ast_node_t* pnode = ex_ast_node_alloc(text, type);
|
|
pnode->pchildren = sllv_alloc();
|
|
sllv_append(pnode->pchildren, pa);
|
|
sllv_append(pnode->pchildren, pb);
|
|
return pnode;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_alloc_ternary(char* text, ex_ast_node_type_t type,
|
|
ex_ast_node_t* pa, ex_ast_node_t* pb, ex_ast_node_t* pc)
|
|
{
|
|
ex_ast_node_t* pnode = ex_ast_node_alloc(text, type);
|
|
pnode->pchildren = sllv_alloc();
|
|
sllv_append(pnode->pchildren, pa);
|
|
sllv_append(pnode->pchildren, pb);
|
|
sllv_append(pnode->pchildren, pc);
|
|
return pnode;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
ex_ast_node_t* ex_ast_node_prepend_arg(
|
|
ex_ast_node_t* pa, ex_ast_node_t* pb)
|
|
{
|
|
if (pa->pchildren == NULL)
|
|
pa->pchildren = sllv_alloc();
|
|
sllv_push(pa->pchildren, pb);
|
|
return pa;
|
|
}
|
|
|
|
ex_ast_node_t* ex_ast_node_append_arg(
|
|
ex_ast_node_t* pa, ex_ast_node_t* pb)
|
|
{
|
|
if (pa->pchildren == NULL)
|
|
pa->pchildren = sllv_alloc();
|
|
sllv_append(pa->pchildren, pb);
|
|
return pa;
|
|
}
|
|
|
|
ex_ast_node_t* ex_ast_node_set_function_name(
|
|
ex_ast_node_t* pa, char* name)
|
|
{
|
|
free(pa->text);
|
|
pa->text = mlr_strdup_or_die(name);
|
|
return pa;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void ex_ast_print(ex_ast_t* past) {
|
|
printf("AST ROOT:\n");
|
|
if (past->proot == NULL) {
|
|
printf("(null)\n");
|
|
} else {
|
|
ex_ast_node_print(past->proot);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
static void ex_ast_node_print_aux(ex_ast_node_t* pnode, int level, FILE* o) {
|
|
if (pnode == NULL)
|
|
return;
|
|
for (int i = 0; i < level; i++)
|
|
fprintf(o, " ");
|
|
fprintf(o, "text=\"%s\", type=%s%s\n",
|
|
pnode->text,
|
|
ex_ast_node_describe_type(pnode->type),
|
|
(pnode->pchildren != NULL) ? ":" : ".");
|
|
if (pnode->pchildren != NULL) {
|
|
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
|
|
ex_ast_node_print_aux(pe->pvvalue, level + 1, o);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ex_ast_node_print(ex_ast_node_t* pnode) {
|
|
ex_ast_node_print_aux(pnode, 0, stdout);
|
|
}
|
|
|
|
void ex_ast_node_fprint(ex_ast_node_t* pnode, FILE* o) {
|
|
ex_ast_node_print_aux(pnode, 0, o);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
char* ex_ast_node_describe_type(ex_ast_node_type_t type) {
|
|
switch(type) {
|
|
case MD_AST_NODE_TYPE_STATEMENT_BLOCK: return "statement_list"; break;
|
|
case MD_AST_NODE_TYPE_BEGIN: return "begin"; break;
|
|
case MD_AST_NODE_TYPE_END: return "end"; break;
|
|
case MD_AST_NODE_TYPE_STRING_LITERAL: return "string_literal"; break;
|
|
case MD_AST_NODE_TYPE_NUMERIC_LITERAL: return "numeric_literal"; break;
|
|
case MD_AST_NODE_TYPE_BOOLEAN_LITERAL: return "boolean_literal"; break;
|
|
case MD_AST_NODE_TYPE_REGEXI: return "regexi"; break;
|
|
case MD_AST_NODE_TYPE_FIELD_NAME: return "field_name"; break;
|
|
case MD_AST_NODE_TYPE_INDIRECT_FIELD_NAME: return "indirect_field_name"; break;
|
|
case MD_AST_NODE_TYPE_FULL_SREC: return "full_srec"; break;
|
|
case MD_AST_NODE_TYPE_OOSVAR_KEYLIST: return "oosvar_keylist"; break;
|
|
case MD_AST_NODE_TYPE_FULL_OOSVAR: return "full_oosvar"; break;
|
|
case MD_AST_NODE_TYPE_NON_SIGIL_NAME: return "non_sigil_name"; break;
|
|
case MD_AST_NODE_TYPE_OPERATOR: return "operator"; break;
|
|
case MD_AST_NODE_TYPE_SREC_ASSIGNMENT: return "srec_assignment"; break;
|
|
case MD_AST_NODE_TYPE_INDIRECT_SREC_ASSIGNMENT: return "indirect_srec_assignment"; break;
|
|
case MD_AST_NODE_TYPE_OOSVAR_ASSIGNMENT: return "oosvar_assignment"; break;
|
|
case MD_AST_NODE_TYPE_OOSVAR_FROM_FULL_SREC_ASSIGNMENT: return "oosvar_from_full_srec_assignment"; break;
|
|
case MD_AST_NODE_TYPE_FULL_SREC_FROM_OOSVAR_ASSIGNMENT: return "full_srec_from_oosvar_assignment"; break;
|
|
case MD_AST_NODE_TYPE_CONTEXT_VARIABLE: return "context_variable"; break;
|
|
case MD_AST_NODE_TYPE_STRIPPED_AWAY: return "stripped_away"; break;
|
|
case MD_AST_NODE_TYPE_CONDITIONAL_BLOCK: return "conditional_block"; break;
|
|
case MD_AST_NODE_TYPE_FILTER: return "filter"; break;
|
|
case MD_AST_NODE_TYPE_UNSET: return "unset"; break;
|
|
case MD_AST_NODE_TYPE_EMITF: return "emitf"; break;
|
|
case MD_AST_NODE_TYPE_EMITF_WRITE: return "emitf_write"; break;
|
|
case MD_AST_NODE_TYPE_EMITF_APPEND: return "emitf_append"; break;
|
|
case MD_AST_NODE_TYPE_EMITP: return "emitp"; break;
|
|
case MD_AST_NODE_TYPE_EMITP_WRITE: return "emitp_write"; break;
|
|
case MD_AST_NODE_TYPE_EMITP_APPEND: return "emitp_append"; break;
|
|
case MD_AST_NODE_TYPE_EMIT: return "emit"; break;
|
|
case MD_AST_NODE_TYPE_EMIT_WRITE: return "emit_write"; break;
|
|
case MD_AST_NODE_TYPE_EMIT_APPEND: return "emit_append"; break;
|
|
case MD_AST_NODE_TYPE_EMITP_LASHED: return "emitp_lashed"; break;
|
|
case MD_AST_NODE_TYPE_EMITP_LASHED_WRITE: return "emitp_lashed_write"; break;
|
|
case MD_AST_NODE_TYPE_EMITP_LASHED_APPEND: return "emitp_lashed_append"; break;
|
|
case MD_AST_NODE_TYPE_EMIT_LASHED: return "emit_lashed"; break;
|
|
case MD_AST_NODE_TYPE_EMIT_LASHED_WRITE: return "emit_lashed_write"; break;
|
|
case MD_AST_NODE_TYPE_EMIT_LASHED_APPEND: return "emit_lashed_append"; break;
|
|
case MD_AST_NODE_TYPE_DUMP: return "dump"; break;
|
|
case MD_AST_NODE_TYPE_DUMP_WRITE: return "dump_write"; break;
|
|
case MD_AST_NODE_TYPE_DUMP_APPEND: return "dump_append"; break;
|
|
case MD_AST_NODE_TYPE_EDUMP: return "edump"; break;
|
|
case MD_AST_NODE_TYPE_PRINT: return "print"; break;
|
|
case MD_AST_NODE_TYPE_PRINT_WRITE: return "print_write"; break;
|
|
case MD_AST_NODE_TYPE_PRINT_APPEND: return "print_append"; break;
|
|
case MD_AST_NODE_TYPE_PRINTN: return "printn"; break;
|
|
case MD_AST_NODE_TYPE_PRINTN_WRITE: return "printn_write"; break;
|
|
case MD_AST_NODE_TYPE_PRINTN_APPEND: return "printn_append"; break;
|
|
case MD_AST_NODE_TYPE_EPRINT: return "eprint"; break;
|
|
case MD_AST_NODE_TYPE_EPRINTN: return "eprintn"; break;
|
|
case MD_AST_NODE_TYPE_ALL: return "all"; break;
|
|
case MD_AST_NODE_TYPE_ENV: return "env"; break;
|
|
case MD_AST_NODE_TYPE_WHILE: return "while"; break;
|
|
case MD_AST_NODE_TYPE_DO_WHILE: return "do_while"; break;
|
|
case MD_AST_NODE_TYPE_FOR_SREC: return "for_srec"; break;
|
|
case MD_AST_NODE_TYPE_FOR_OOSVAR: return "for_oosvar"; break;
|
|
case MD_AST_NODE_TYPE_FOR_VARIABLES: return "for_variables"; break;
|
|
case MD_AST_NODE_TYPE_NONINDEXED_LOCAL_VARIABLE: return "local_variable"; break;
|
|
case MD_AST_NODE_TYPE_IN: return "in"; break;
|
|
case MD_AST_NODE_TYPE_BREAK: return "break"; break;
|
|
case MD_AST_NODE_TYPE_CONTINUE: return "continue"; break;
|
|
case MD_AST_NODE_TYPE_IF_HEAD: return "if_head"; break;
|
|
case MD_AST_NODE_TYPE_IF_ITEM: return "if_item"; break;
|
|
default: return "???";
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void ex_ast_free(ex_ast_t* past) {
|
|
ex_ast_node_free(past->proot);
|
|
free(past);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void ex_ast_node_free(ex_ast_node_t* pnode) {
|
|
if (pnode->pchildren) {
|
|
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
|
|
ex_ast_node_t* pchild = pe->pvvalue;
|
|
ex_ast_node_free(pchild);
|
|
}
|
|
sllv_free(pnode->pchildren);
|
|
}
|
|
free(pnode->text);
|
|
free(pnode);
|
|
}
|