commit 8de30f6330165bf0b1ba05155030318f34190f47
parent 9a911ac4ee93084336a8f55d6815615b09b6b722
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 25 Mar 2014 18:38:40 +0100
First version with some semantic analysis
Diffstat:
M | decl.c | | | 15 | ++++++++++----- |
M | expr.c | | | 148 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
M | stmt.c | | | 4 | ++-- |
M | symbol.h | | | 18 | ++++++++++-------- |
4 files changed, 155 insertions(+), 30 deletions(-)
diff --git a/decl.c b/decl.c
@@ -140,6 +140,7 @@ declarator(struct ctype *tp, uint8_t ns, int8_t flags)
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 @@ typename(void)
void
extdecl(void)
{
- struct ctype *tp;
+ struct ctype *base;
int8_t sclass;
struct symbol *sym;
char *err;
@@ -481,7 +482,7 @@ extdecl(void)
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 @@ extdecl(void)
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 @@ extdecl(void)
if (sclass & EXTERN)
; /* TODO: handle extern */
else if (accept('='))
- initializer(sym->type);
+ initializer(tp);
}
} while (accept(','));
}
diff --git 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 @@ primary(void)
break;
case '(':
next();
- tp = expr();
+ np = expr();
expect(')');
break;
default:
- error("unexpected '%s'", yytoken);
+ error("unexpected '%s'", yytext);
+ }
+ return np;
+}
+
+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;
}
- return tp;
+ 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 ctype *
+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
diff --git 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 @@ compound(void)
decl();
break;
default:
- expr();
+ eval(expr());
}
expect(';');
}
diff --git a/symbol.h b/symbol.h
@@ -97,14 +97,16 @@ extern struct ctype *voidtype,
*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