#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include "ast.h"
#include "cibic.tab.h"
#define NEW_CNODE ((CNode *)malloc(sizeof(CNode)))
CNode *ast_root;
void cnode_init() {
}
CNode *cnode_create_nop() {
CNode *nop = NEW_CNODE;
nop->type = NOP;
nop->next = nop->chd = NULL;
return nop;
}
CNode *cnode_create_general(int type, int subtype, int pnum, va_list ap) {
int i;
CNode *exp = NEW_CNODE;
exp->type = type;
exp->rec.subtype = subtype;
exp->next = NULL;
for (i = 0; i < pnum; i++)
{
CNode *subexp = va_arg(ap, CNode*);
if (subexp->next)
{
puts("asdf");
}
assert(subexp->next == NULL);
subexp->next = exp->chd;
exp->chd = subexp;
}
return exp;
}
CNode *cnode_append(CNode *node, CNode *tail) {
if (node->type == NOP)
{
free(node);
return tail;
}
tail->next = node;
return tail;
}
CNode *cnode_create_identifier(char *val) {
CNode *exp = NEW_CNODE;
exp->type = ID;
exp->chd = exp->next = NULL;
exp->rec.strval = val;
return exp;
}
CNode *cnode_create_int_const(int val) {
/* TODO: overflow checking */
CNode *exp = NEW_CNODE;
exp->type = INT;
exp->chd = exp->next = NULL;
exp->rec.intval = val;
return exp;
}
CNode *cnode_create_char_const(int val) {
/* TODO: overflow checking */
CNode *exp = NEW_CNODE;
exp->type = CHAR;
exp->chd = exp->next = NULL;
exp->rec.intval = val;
return exp;
}
CNode *cnode_create_str_const(char *val) {
CNode *exp = NEW_CNODE;
exp->type = STR;
exp->chd = exp->next = NULL;
exp->rec.strval = val;
return exp;
}
CNode *cnode_create_exp(int exp_type, int pnum, ...) {
CNode *ret;
va_list ap;
va_start(ap, pnum);
ret = cnode_create_general(EXP, exp_type, pnum, ap);
va_end(ap);
return ret;
}
CNode *cnode_create_type_spec(int spec_type, int pnum, ...) {
CNode *ret;
va_list ap;
va_start(ap, pnum);
ret = cnode_create_general(TYPE_SPEC, spec_type, pnum, ap);
va_end(ap);
return ret;
}
CNode *cnode_create_declr(int declr_type, int pnum, ...) {
CNode *ret;
va_list ap;
va_start(ap, pnum);
ret = cnode_create_general(DECLR, declr_type, pnum, ap);
va_end(ap);
return ret;
}
CNode *cnode_create_stmt(int stmt_type, int pnum, ...) {
CNode *ret;
va_list ap;
va_start(ap, pnum);
ret = cnode_create_general(STMT, stmt_type, pnum, ap);
va_end(ap);
return ret;
}
CNode *cnode_create_initr(int initr_type, CNode *body) {
CNode *initr = NEW_CNODE;
initr->type = INITR;
initr->rec.subtype = initr_type;
initr->chd = body;
return initr;
}
CNode *cnode_create_decl(CNode *type, CNode *init_declrs) {
CNode *decl = NEW_CNODE;
decl->type = DECL;
decl->chd = type;
type->next = init_declrs;
return decl;
}
CNode *cnode_create_func(CNode *type, CNode *plain_decl, CNode *params, CNode *stmt) {
CNode *func = NEW_CNODE;
func->type = FUNC_DEF;
func->chd = stmt;
func->next = NULL;
stmt->next = params;
params->next = plain_decl;
plain_decl->next = type;
return func;
}
CNode *cnode_create_init_declr(CNode *declr, CNode *initr) {
CNode *init_declr = NEW_CNODE;
init_declr->type = INIT_DECLR;
init_declr->chd = initr;
initr->next = declr;
return init_declr;
}
CNode *cnode_create_struct_field(CNode *type_spec, CNode *declrs) {
CNode *field = NEW_CNODE;
field->type = FIELD;
field->chd = declrs;
declrs->next = type_spec;
return field;
}
CNode *cnode_create_plain_decl(CNode *type_spec, CNode *declr) {
CNode *pdecl = NEW_CNODE;
pdecl->type = PLAIN_DECL;
pdecl->chd = declr;
declr->next = type_spec;
return pdecl;
}
CNode *cnode_create_comp_decls(CNode *decls) {
CNode *comp_decls = NEW_CNODE;
comp_decls->type = COMP_DECLS;
comp_decls->chd = decls;
return comp_decls;
}
CNode *cnode_create_comp_stmts(CNode *stmts) {
CNode *comp_stmts = NEW_CNODE;
comp_stmts->type = COMP_STMTS;
comp_stmts->chd = stmts;
comp_stmts->next = NULL;
return comp_stmts;
}
CNode *cnode_create_args(CNode *arg_list) {
CNode *args = NEW_CNODE;
args->type = ARGS;
args->chd = arg_list;
args->next = NULL;
return args;
}
CNode *cnode_create_params(CNode *plist) {
CNode *params = NEW_CNODE;
params->type = PARAMS;
params->chd = plist;
params->next = NULL;
return params;
}
char *cnode_debug_type_repr(CNode *ast) {
static buffer[1024];
char *type = NULL;
switch (ast->type)
{
case PROG: type = "prog"; break;
case FUNC_DEF: type = "func"; break;
case DECL: type = "decl"; break;
case DECLR: type = "declr"; break;
case INIT_DECLR: type = "init_declr"; break;
case PLAIN_DECL: type = "p_decl"; break;
case TYPE_NAME: type = "type_name"; break;
case COMP_STMTS: type = "stmts"; break;
case COMP_DECLS: type = "decls"; break;
case ARGS: type = "args"; break;
case PARAMS: type = "params"; break;
case ID: type = "id"; break;
case INT: type = "int"; break;
case CHAR: type = "char"; break;
case STR: type = "str"; break;
case NOP: type = "nop"; break;
}
if (ast->type == EXP)
{
switch (ast->rec.subtype)
{
case ',': type = ","; break;
case '=': type = "="; break;
case ASS_MUL: type = "*="; break;
case ASS_DIV: type