ref: 7d77cd4c9f3bd9c9a4ad49890b08a4181552ff3d
dir: /tree.c/
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "cc.h"
#include "syntax.h"
#include "symbol.h"
struct node {
unsigned char op;
};
struct node_op1 {
struct node base;
struct node *infix;
};
struct node_op2 {
struct node base;
struct node *left;
struct node *rigth;
};
struct node_sym {
struct node base;
struct symbol *sym;
};
struct node_comp {
struct node base;
uint8_t nr, alloc;
struct node **body;
};
static unsigned char indent; /* used for pretty printing the tree*/
struct node *
nodesym(struct symbol *sym)
{
register struct node_sym *np = xmalloc(sizeof(*np));
np->base.op = OSYM;
np->sym = sym;
return (struct node *) np;
}
struct node *
node(unsigned char op, struct node *l, struct node *r)
{
register struct node_op2 *np = xmalloc(sizeof(*np));
np->base.op = op;
np->left = l;
np->rigth = r;
return (struct node *) np;
}
struct node *
node1(unsigned char op, struct node *i)
{
register struct node_op1 *np = xmalloc(sizeof(*np));
np->base.op = op;
np->infix = i;
return (struct node *) np;
}
struct node *
nodecomp(void)
{
register struct node_comp *np = xmalloc(sizeof(*np));
np->base.op = OCOMP;
np->alloc = np->nr = 0;
np->body = NULL;
return (struct node *) np;
}
struct node *
addstmt(struct node *p, struct node *stmt)
{
register uint8_t nr, alloc;
register struct node_comp *np = (struct node_comp *) p;
assert(np && np->base.op == OCOMP);
nr = ++np->nr, alloc = np->alloc;
#define alloc_nr(x) ((((x)+16)*3)/2)
if (nr > alloc) {
alloc = alloc_nr(nr);
np->body = xrealloc(np->body, alloc * sizeof(*np->body));
}
#undef alloc_nr
np->body[nr - 1] = stmt;
np->alloc = alloc;
return p;
}
static void
prtree_helper(register struct node *np)
{
static struct optab {
unsigned char nchild;
const char *txt;
} *bp, optab [] = {
[OCALL] = {1, "()"},
[OARY] = {2, "[]"},
[OFIELD] = {2, "."},
[OPTR] = {2, "->"},
[OPOSTINC] = {1, ".++"},
[OPOSTDEC] = {1, ".--"},
[OPREINC] = {1, "++."},
[OPREDEC] = {1, "--."},
[OADDR] = {1, "&."},
[OINDIR] = {1, "[*]"},
[OMINUS] = {1, "-."},
[OPLUS] = {1, "+."},
[OCPL] = {1, "~"},
[ONEG] = {1, "!"},
[OMUL] = {2, "*"},
[ODIV] = {2, "/"},
[OMOD] = {2, "%"},
[OADD] = {2, "+"},
[OSUB] = {2, "-"},
[OSHL] = {2, "<<"},
[OSHR] = {2, ">>"},
[OLT] = {2, "<"},
[OGT] = {2, ">"},
[OGE] = {2, ">="},
[OLE] = {2, "<="},
[OEQ] = {2, "=="},
[ONE] = {2, "!="},
[OBAND] = {2, "&"},
[OBXOR] = {2, "^"},
[OBOR] = {2, "|"},
[OAND] = {2, "&&"},
[OOR] = {2, "||"},
[OTERN] = {2, "?"},
[OASSIGN] = {2, "="},
[OA_MUL] = {2, "*="},
[OA_DIV] = {2, "/="},
[OA_MOD] = {2, "%="},
[OA_ADD] = {2, "+="},
[OA_SUB] = {2, "-="},
[OA_SHL] = {2, "<<="},
[OA_SHR] = {2, ">>="},
[OA_AND] = {2, "&="},
[OA_XOR] = {2, "^="},
[OA_OR] = {2, "|="},
[OSYM] = {0, "sym"},
[OCOMP] = {255, "comp"},
[OSWITCH] = {2, "switch"},
[OIF] = {2, "if"},
[OFOR] = {2, "for"},
[OFEXP] = {2, "efor"},
[ODO] = {2, "do"},
[OWHILE] = {2, "while"},
[OLABEL] = {2, "label"},
[OGOTO] = {1, "goto"},
[OBREAK] = {1, "break"},
[OCONT] = {1, "cont"},
[ORETURN] = {1, "return"},
[OCASE] = {1, "case"},
[ODEFAULT] = {1, "default"},
[OFTN] = {1, "function"},
[ODEF] = {2, "def"},
[O2EXP] = { 2, ":"}
};
if (!np) {
fputs(" nil", stdout);
return;
}
assert(np->op < ARRAY_SIZE(optab));
bp = &optab[np->op];
if (bp->nchild) {
register unsigned char i;
putchar('\n');
for (i = indent; i != 0; --i)
putchar(' ');
printf("(%s", bp->txt);
indent += 2;
}
switch (bp->nchild) {
case 0: {
register struct symbol *sym = ((struct node_sym *) np)->sym;
putchar(' ');
fputs((sym->name) ? sym->name : ".", stdout);
return;
}
case 1:
prtree_helper(((struct node_op1 *) np)->infix);
break;
case 2:
prtree_helper(((struct node_op2 *) np)->left);
prtree_helper(((struct node_op2 *) np)->rigth);
break;
case 255: {
register struct node **bp, **lim;
bp = ((struct node_comp *) np)->body;
lim = bp + ((struct node_comp *) np)->nr;
while (bp < lim)
prtree_helper(*bp++);
break;
}
}
putchar(')');
indent -= 2;
}
void
prtree(register struct node *np)
{
indent = 0;
prtree_helper(np);
}