shithub: scc

ref: 449b361b5e44127d7ca45773cab7d8f4c4b496df
dir: /expr.c/

View raw version
#include <stddef.h>
#include <stdio.h>

#include "cc.h"
#include "tokens.h"
#include "symbol.h"
#include "syntax.h"


struct node *expr(void);

static struct node *
primary(void)
{
	register struct node *np;
	register struct symbol *sym;

	switch (yytoken) {
	case IDEN:
		sym = lookup(yytext, NS_IDEN);
		if (!sym->ctype.defined)
			error("'%s' undeclared", yytext);
		next();
		np = nodesym(sym);
		break;
	case CONSTANT:
		sym = yyval;
		next();
		np = nodesym(sym);
		break;
	case '(':
		next();
		np = expr();
		expect(')');
		break;
	default:
		np = NULL;
		break;
	}
	return np;
}

static struct node *
postfix(void)
{
	register struct node *np1, *np2;

	np1 = primary();		/* TODO: fix ( case */
	for (;;) {
		register unsigned char op;
		switch (yytoken) {
		case '[':
			next();
			np2 = expr();
			expect(']');
			op = OARY;
			goto node_2_childs; /* TODO: better names */
		case '(':
			next();
			np2 = expr();
			expect(')');
			op = OCALL;
			goto node_2_childs;
		case '.':   op = OFIELD; goto expect_iden;
		case INDIR: op = OPTR; goto expect_iden;
		case INC:   op = OPOSTINC; goto next;
		case DEC:   op = OPOSTDEC; goto next;
		default:    return np1;
		}
	expect_iden:
		next();
		expect(IDEN);
		np2 = nodesym(lookup(yytext, NS_IDEN));
	node_2_childs:
		np1 = node(op, np1, np2);
		continue;
	next:
		np1 = node(op, np1, NULL);
		next();
		continue;
	}
}

static struct node *cast(void);

static struct node *
unary(void)
{
	register unsigned char op;

	switch (yytoken) {
	case SIZEOF:		/* TODO: Implement sizeof */
		next();
		if (accept('(')) {
			type_name();
			expect(')');
		} else {
			unary();
		}
		return nodesym(NULL);
	case INC: op = OPREINC; goto call_unary;
	case DEC: op = OPREDEC; goto call_unary;
	case '&': op = OADDR;  goto call_cast;
	case '*': op = OINDIR; goto call_cast;
	case '-': op = OMINUS; goto call_cast;
	case '+': op = OPLUS; goto call_cast;
	case '~': op = OCPL; goto call_cast;
	case '!': op = ONEG; goto call_cast;
	default: return postfix();
	}

call_cast:
	next();
	return node(op, cast(), NULL);

call_unary:
	next();
	return node(op, unary(), NULL);
}

static struct node *
cast(void)
{
	while (accept('(')) {	/* TODO: Implement casts */
		type_name();	/* check if it really is a type name */
		expect(')');
	}
	return unary();
}

static struct node *
mul(void)
{
	register struct node *np;
	register unsigned char op;

	np = cast();
	for (;;) {
		switch (yytoken) {
		case '*': op = OMUL; break;
		case '/': op = ODIV; break;
		case '%': op = OMOD; break;
		default:  return np;
		}
		next();
		np = node(op, np, cast());
	}
}

static struct node *
add(void)
{
	register unsigned char op;
	register struct node *np;

	np = mul();
	for (;;) {
		switch (yytoken) {
		case '+': op = OADD; break;
		case '-': op = OSUB; break;
		default:  return np;
		}
		next();
		np = node(op, np, mul());
	}
}

static struct node *
shift(void)
{
	register unsigned char op;
	register struct node *np;

	np = add();
	for (;;) {
		switch (yytoken) {
		case SHL: op = OSHL; break;
		case SHR: op = OSHR; break;
		default:  return np;
		}
		next();
		np = node(op, np, add());
	}
}

static struct node *
relational(void)
{
	register unsigned char op;
	register struct node *np;

	np = shift();
	for (;;) {
		switch (yytoken) {
		case '<': op = OLT; break;
		case '>': op = OGT; break;
		case GE:  op = OGE; break;
		case LE:  op = OLE; break;
		default:  return np;
		}
		next();
		np = node(op, np, shift());
	}
}

static struct node *
eq(void)
{
	register unsigned char op;
	register struct node *np;

	np = relational();
	for (;;) {
		switch (yytoken) {
		case EQ: op = OEQ; break;
		case NE: op = ONE; break;
		default: return np;
		}
		next();
		np = node(op, np, relational());
	}
}

static struct node *
bit_and(void)
{
	register struct node *np;

	np = eq();
	while (yytoken == '&') {
		next();
		np = node(OBAND, np, eq());
	}
	return np;
}

static struct node *
bit_xor(void)
{
	register struct node *np;

	np = bit_and();
	while (yytoken == '^') {
		next();
		np = node(OBXOR, np, bit_and());
	}
	return np;
}

static struct node *
bit_or(void)
{
	register struct node *np;

	np = bit_xor();
	while (yytoken == '|') {
		next();
		np = node(OBOR, np, bit_xor());
	}
	return np;
}

static struct node *
and(void)
{
	register struct node *np;

	np = bit_or();
	while (yytoken == AND) {
		next();
		np = node(OAND, np, bit_or());
	}
	return np;
}

static struct node *
or(void)
{
	register struct node *np;

	np = and();
	while (yytoken == OR) {
		next();
		np = node(OOR, np, and());
	}
	return np;
}

static struct node *
cond(void)
{
	register struct node *np, *aux;

	np = or();
	while (yytoken == '?') {
		aux = expr();
		expect(':');
		np = node(OTERN, np,
		          node(O2EXP, aux, or()));
	}
	return np;
}

static struct node *
assign(void)
{
	register struct node *np = cond();

	for (;;) {
		register unsigned char op;

		switch (yytoken) {
		case '=':    op = OASSIGN; break;
		case MUL_EQ: op = OA_MUL;  break;
		case DIV_EQ: op = OA_DIV;  break;
		case MOD_EQ: op = OA_MOD;  break;
		case ADD_EQ: op = OA_ADD;  break;
		case SUB_EQ: op = OA_SUB;  break;
		case SHL_EQ: op = OA_SHL;  break;
		case SHR_EQ: op = OA_SHR;  break;
		case AND_EQ: op = OA_AND;  break;
		case XOR_EQ: op = OA_XOR;  break;
		case OR_EQ:  op = OA_OR;   break;
		default:  goto return_np;
		}
		next();
		np = node(op, np, assign());
	}
return_np:
	return np;
}

struct node *
expr(void)
{
	register struct node *np;

	do
		np = assign();
	while (yytoken == ',');

	return np;
}