shithub: scc

ref: 439fd8a6d2e636acabe21de2b9223d1030adc8b0
dir: /tree.c/

View raw version

#include <assert.h>
#include <stddef.h>
#include <stdio.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_op3 {
	struct node base;
	struct node *left;
	struct node *infix;
	struct node *rigth;
};

struct node_sym {
	struct node base;
	struct symbol *sym;
};

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 *
node3(unsigned char op, struct node *l, struct node *i, struct node *r)
{
	register struct node_op3 *np = xmalloc(sizeof(*np));

	np->base.op = op;
	np->left = l;
	np->infix = i;
	np->rigth = r;

	return (struct node *) np;
}

struct node *
node2(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;
}

void
prtree(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] = {3, "?"},
		[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"}
	};

	assert(np && np->op < ARRAY_SIZE(optab));
	bp = &optab[np->op];
	if (bp->nchild)
		printf("(%s ", bp->txt);

	switch (bp->nchild) {
	case 0: {
		register struct symbol *sym = ((struct node_sym *) np)->sym;
		printf(" %s", (sym->name) ? sym->name : ".");
		return;
	}
	case 1:
		prtree(((struct node_op1 *) np)->infix);
		break;
	case 2:
		prtree(((struct node_op2 *) np)->left);
		prtree(((struct node_op2 *) np)->rigth);
		break;
	case 3:
		prtree(((struct node_op3 *) np)->left);
		prtree(((struct node_op3 *) np)->infix);
		prtree(((struct node_op3 *) np)->rigth);
		break;
	}
	putchar(')');
}