shithub: scc

Download patch

ref: 8de30f6330165bf0b1ba05155030318f34190f47
parent: 9a911ac4ee93084336a8f55d6815615b09b6b722
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Mar 25 14:38:40 EDT 2014

First version with some semantic analysis

--- a/decl.c
+++ b/decl.c
@@ -140,6 +140,7 @@
 	register struct dcldata *bp;
 	struct symbol *sym;
 
+	memset(data, 0, sizeof(data));
 	data[NR_DECLARATORS].op = 255;
 	for (bp = declarator0(data, ns, flags); bp >= data; --bp) {
 		switch (bp->op) {
@@ -471,7 +472,7 @@
 void
 extdecl(void)
 {
-	struct ctype *tp;
+	struct ctype *base;
 	int8_t sclass;
 	struct symbol *sym;
 	char *err;
@@ -481,7 +482,7 @@
 
 	switch (yytoken) {
 	case IDEN: case TYPE: case SCLASS: case TQUALIFIER:
-		tp = specifier(&sclass);
+		base = specifier(&sclass);
 		if (sclass == REGISTER || sclass == AUTO)
 			goto bad_storage;
 	case ';':
@@ -492,10 +493,14 @@
 
 	if (yytoken != ';') {
 		do {
-			sym = declarator(tp, NS_IDEN, ID_EXPECTED);
+			struct ctype *tp;
+
+			sym = declarator(base, NS_IDEN, ID_EXPECTED);
+			tp = sym->type;
+
 			if (!(sclass & STATIC))
 				sym->s.isglobal = 1;
-			if (ISFUN(sym->type)) {
+			if (isfun(BTYPE(tp))) {
 				emitfun(sym);
 				if (yytoken == '{') {
 					emitframe(sym);
@@ -509,7 +514,7 @@
 				if (sclass & EXTERN)
 					; /* TODO: handle extern */
 				else if (accept('='))
-					initializer(sym->type);
+					initializer(tp);
 			}
 		} while (accept(','));
 	}
--- a/expr.c
+++ b/expr.c
@@ -6,20 +6,46 @@
 #include "tokens.h"
 #include "symbol.h"
 
+struct node *expr(void);
 
-struct ctype *expr(void);
+enum {
+	OSYM = 1, OARY, OADDR, OADD
+};
 
-static struct ctype *
+struct node {
+	uint8_t op;
+	struct ctype *type;
+
+	struct {
+		bool constant : 1;
+	} f;
+	union  {
+		struct symbol *sym;
+	} u;
+	struct node *left, *right;
+};
+
+struct node *
+newnode(uint8_t op, struct ctype *tp)
+{
+	struct node *np = xcalloc(1, sizeof(*np));
+
+	np->op = op;
+	np->type = tp;
+	return np;	
+}
+
+static struct node *
 primary(void)
 {
-	register struct ctype *tp;
+	register struct node *np;
 
 	switch (yytoken) {
 	case IDEN:
 		if (yylval.sym == NULL)
 			error("'%s' undeclared", yytext);
-		emitsym(yylval.sym);
-		tp = yylval.sym->type;
+		np = newnode(OSYM, yylval.sym->type);
+		np->u.sym = yylval.sym;
 		next();
 		break;
 	case CONSTANT:
@@ -28,31 +54,122 @@
 		break;
 	case '(':
 		next();
-		tp = expr();
+		np = expr();
 		expect(')');
 		break;
 	default:
-		error("unexpected '%s'", yytoken);
+		error("unexpected '%s'", yytext);
 	}
-	return tp;
+	return np;
 }
 
-static struct ctype *
+static struct node *
+ary2ptr(struct node *np)
+{
+	struct ctype *tp = np->type;
+
+	struct node *aux;
+
+	tp = mktype(UNQUAL(tp)->type, PTR, NULL, 0);
+	aux= newnode(OADDR, tp);
+	aux->left = np;
+	return aux;
+}
+
+static struct node *
+int2ptr(struct node *np)
+{
+	return np;
+}
+
+static struct node *
+ary(struct node *np1)
+{
+	struct node *np2,  *naux;
+	struct ctype *tp;
+	uint8_t t1, t2, taux;
+
+	np2 = expr();
+	expect(']');
+	t1 = BTYPE(np1->type);
+	t2 = BTYPE(np2->type);
+
+	if (!isaddr(t1)) {
+		taux = t1,   t1 = t2,   t2 = taux;
+		naux = np1, np1 = np2, np2 = naux;
+	}
+	if (!isaddr(t1))
+		error("expected array or pointer");
+	if (isary(t1))
+		np1 = ary2ptr(np1);
+	if (!isarith(t2))
+		error("array subscript is not an integer");
+
+	tp = np1->type;
+	tp = UNQUAL(tp);
+	naux = newnode(OADD, tp);
+	naux->left = np1;
+	naux->right = int2ptr(np2);
+	return naux;
+}
+
+static struct node *
 postfix(void)
 {
-	struct ctype * tp;
+	struct node *np;
 
-	tp = primary();
+	np = primary();
+	for (;;) {
+		switch (yytoken) {
+		case '[': next(); np = ary(np); break;
+		default: return np;
+		}
+	}			
 }
 
-struct ctype *
+struct node *
 expr(void)
 {
-	register struct ctype *tp;
+	register struct node *np;
 
 	do
-		tp = postfix();
+		np = postfix();
 	while (yytoken == ',');
 
-	return tp;
+	return np;
 }
+
+static void
+evalnode(struct node *np)
+{
+	if (!np)
+		return;
+
+	switch (np->op) {
+	case OSYM:
+		emitsym(np->u.sym);
+		break;
+	case OARY:
+		evalnode(np->left);
+		evalnode(np->right);
+		fputs("\t'", stdout);
+		break;
+	case OADDR:
+		evalnode(np->left);
+		evalnode(np->right);
+		fputs("\t@", stdout);
+		break;
+	case OADD:
+		evalnode(np->left);
+		evalnode(np->right);
+		fputs("\t+", stdout);
+		break;
+	}
+}
+
+void
+eval(struct node *np)
+{
+	evalnode(np);
+	putchar('\n');
+}
\ No newline at end of file
--- a/stmt.c
+++ b/stmt.c
@@ -8,7 +8,7 @@
 void
 compound(void)
 {
-	extern struct ctype *expr(void);
+	extern struct node *expr(void);
 	extern void decl(void);
 
 	expect('{');
@@ -18,7 +18,7 @@
 			decl();
 			break;
 		default:
-			expr();
+			eval(expr());
 		}
 		expect(';');
 	}
--- a/symbol.h
+++ b/symbol.h
@@ -97,14 +97,16 @@
 	*doubletype,  *cdoubletype, *idoubletype,
 	*ldoubletype, *cldoubletype,*ildoubletype;
 
-#define UNQUAL(t)   (ISQUAL(t) ? (t)->type : (t))
-#define BTYPE(t)    (UNQUAL(t)->op)
-#define ISFUN(t)    ((t)->op == FTN)
-#define ISPTR(t)    ((t)->op == PTR)
-#define ISARITH(t)  ((t)->op & ARITH)
-#define ISADDR(t)   ((t)->op & POINTER)
-#define ISRECORD(t) ((t)->op & RECORD)
-#define ISQUAL(t)   ((t)->op & TQUALIFIER)
+#define ISQUAL(t)    (isqual((t)->op))
+#define UNQUAL(t)    (ISQUAL(t) ? (t)->type : (t))
+#define BTYPE(t)     (UNQUAL(t)->op)
+#define isfun(op)    ((op) == FTN)
+#define isptr(op)    ((op) == PTR)
+#define isary(op)    ((op) == ARY)
+#define isarith(op)  ((op) & ARITH)
+#define isaddr(op)   ((op) & POINTER)
+#define isrecord(op) ((op) & RECORD)
+#define isqual(op)   ((op) & TQUALIFIER)
 
 
 #endif
--