aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/cc/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/cc/ast.c')
-rw-r--r--sys/cmd/cc/ast.c284
1 files changed, 231 insertions, 53 deletions
diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c
index 825bade..dd9b03b 100644
--- a/sys/cmd/cc/ast.c
+++ b/sys/cmd/cc/ast.c
@@ -1,4 +1,8 @@
#include "cc.h"
+
+// -----------------------------------------------------------------------
+// helper macros
+
#define alloc(ptr) (ptr) = mem·arenaalloc(C.heap, 1, sizeof *(ptr))
#define movearray(dst, arr, n) (dst) = mem·arenaalloc(C.heap, (n), sizeof *(arr)), memcpy((dst), (arr), n * sizeof *(arr)), free(arr)
@@ -18,7 +22,7 @@ nameof(Name *n)
if (n->kind & Nident)
return n->ident;
if (n->kind & Nparen)
- return nameof(&n->paren->name);
+ return nameof(n->paren->name);
panicf("ill-formed declarator name");
}
@@ -48,6 +52,46 @@ closescope(Parser *p)
p->sp--;
}
+static
+Dtor*
+getdtor(Parser *p)
+{
+ if (p->dt >= p->dtstk + arrlen(p->dtstk)) {
+ panicf("out of dtor buffer space");
+ }
+ return p->dt++;
+}
+
+static
+void
+putdtor(Parser *p)
+{
+ if (p->dt == p->dtstk) {
+ panicf("too many frees of dtor buffer space");
+ }
+ *p->dt-- = (Dtor){0};
+}
+
+static
+Name*
+getname(Parser *p)
+{
+ if (p->nm >= p->nmstk + arrlen(p->nmstk)) {
+ panicf("out of dtor buffer space");
+ }
+ return p->nm++;
+}
+
+static
+void
+putname(Parser *p)
+{
+ if (p->nm == p->nmstk) {
+ panicf("too many frees of dtor buffer space");
+ }
+ *p->nm-- = (Name){0};
+}
+
#if 0
static
void
@@ -393,9 +437,10 @@ static
Type*
type(Parser *p, Lexer *lx)
{
- Dtor dt;
uint64 sp;
+ Dtor *dt;
+ dt = getdtor(p);
if (spec(p, lx, &sp)) {
errorat(lx->pos, "invalid type specification");
goto Bad;
@@ -404,11 +449,11 @@ type(Parser *p, Lexer *lx)
errorat(lx->pos, "invalid type specifier");
goto Bad;
}
- if (dtor(p, lx, &dt, 1)) {
+ if (dtor(p, lx, dt, 1)) {
errorat(lx->pos, "invalid declarator");
goto Bad;
}
- if (nameof(&dt.name) != nil) {
+ if (nameof(dt->name) != nil) {
errorat(lx->pos, "abstract declarator can not have an identifier");
goto Bad;
}
@@ -933,21 +978,19 @@ blkstmt(Parser *p, Lexer *lx, Stmt **s)
t = peek(p, 0);
if (nomatch(t, Albrakt))
goto Bad;
- advance(p, lx);
+ t = advance(p, lx);
len = 0, cap = 20;
ns = malloc(cap*sizeof(*ns));
- for (;;) {
+ while (t.kind != Arbrakt) {
if (cap == len) {
cap += 20;
ns = realloc(ns, cap*sizeof(*ns));
}
ns[len++] = stmt(p, lx);
+ t = peek(p, 0);
}
- if (nomatch(t, Arbrakt))
- goto Bad;
-
(*s)->pos.end = lx->pos;
(*s)->blk.n = len;
movearray((*s)->blk.item, ns, len);
@@ -1082,29 +1125,43 @@ Bad:
/* name declaration */
static
error
-name(Parser *p, Lexer *lx, Name *nm, int ab)
+name(Parser *p, Lexer *lx, Name **nmp, int ab)
{
+ Token t;
int n, k;
- Token t;
+ uint64 s;
+ Sym *sym;
+ Name *nm, *tmp;
- t = peek(p, 0);
+ /* i don't think i have to worry about multiple uses here */
+ string args[100];
+ Type types[100];
+
+ nm = *nmp;
+ t = peek(p, 0);
switch (k = t.kind) {
case Aident:
+ if (ab) {
+ errorat(t.pos, "identifier not allowed in abstract declarator");
+ goto Bad;
+ }
nm->kind = Nident;
nm->ident = t.val.s;
break;
case Alparen:
nm->kind = Nparen;
- alloc(nm->paren);
+ nm->paren = getdtor(p);
if (dtor(p, lx, nm->paren, ab)) {
- /* we are using an arena allocator so can't clean up */
- errorat(lx->pos, "invalid declarator in parenthesis");
+ putdtor(p);
nm->paren = nil;
+ errorat(lx->pos, "invalid declarator in parenthesis");
goto Bad;
}
t = peek(p, 0);
if (t.kind != Arparen) {
+ putdtor(p);
+ nm->paren = nil;
errorat(lx->pos, "missing closing paren in declarator");
goto Bad;
}
@@ -1121,21 +1178,113 @@ name(Parser *p, Lexer *lx, Name *nm, int ab)
}
t = advance(p, lx);
- switch (k = t.kind) {
- case Albrakt:
- nm->kind |= Nindex;
- panicf("need to implement");
- break;
+ for (;;) {
+ switch (k = t.kind) {
+ case Albrakt:
+ tmp = getname(p);
+ tmp->kind = Nindex;
+ tmp->sfx.name = nm;
- case Alparen:
- nm->kind |= Ncall;
- panicf("need to implement");
- break;
+ nm = tmp, tmp = nil;
- default:
- ;
+ t = advance(p, lx);
+ if (t.kind == Arbrakt) {
+ nm->sfx.idx.q = 0;
+ Iend:
+ nm->sfx.idx.x = nil;
+ t = advance(p, lx);
+ break;
+ }
+ if (t.kind == Astar) {
+ nm->sfx.idx.q = -1;
+ IStar:
+ nm->sfx.idx.x = nil;
+ t = advance(p, lx);
+ if (t.kind != Arbrakt) {
+ errorat(t.pos, "invalid '*' syntax in index expression");
+ goto Bad;
+ }
+ t = advance(p, lx);
+ break;
+ }
+
+ if (spec(p, lx, &s)) {
+ errorat(lx->pos, "invalid type qualifier list in index expression");
+ goto Bad;
+ }
+
+ nm->sfx.idx.q = (uint32)s;
+ t = peek(p, 0);
+
+ if (t.kind == Astar)
+ goto IStar;
+
+ if (t.kind == Arbrakt)
+ goto Iend;
+
+ nm->sfx.idx.x = expr(p, lx);
+
+ t = peek(p, 0);
+ if (nomatch(t, Arbrakt)) {
+ errorat(lx->pos, "unterminated index expression");
+ goto Bad;
+ }
+
+ t = advance(p, lx);
+ continue;
+
+ case Alparen:
+ tmp = getname(p);
+ tmp->kind = Ncall;
+ tmp->sfx.name = nm;
+
+ nm = tmp, tmp = nil;
+
+ t = advance(p, lx);
+ nm->sfx.call.n = 0;
+ switch (t.kind) {
+ case Arparen:
+ nm->sfx.call.arg = nil;
+ break;
+
+ case Aident:
+ sym = lookupobj(p, t.val.s);
+ if (!sym || (sym && sym->kind != Stype)) {
+ while (t.kind == Aident) {
+ args[nm->sfx.call.n++] = t.val.s;
+ t = advance(p, lx);
+ }
+ if (nomatch(t, Arparen)) {
+ errorat(t.pos, "token '%s' found in function parameter identifier list");
+ goto Bad;
+ }
+ break;
+ }
+ goto Params;
+
+ case Akeywd:
+ if (t.val.i < Kconst || t.val.i == Knoret || t.val.i == Kinline || t.val.i > Kenum) {
+ errorat(t.pos, "invalid keyword %s inside function signature");
+ goto Bad;
+ }
+
+ Params:
+
+ default:
+ errorat(t.pos, "invalid token %s inside function call signature", tokens[t.kind]);
+ goto Bad;
+ }
+
+ t = advance(p, lx);
+ continue;
+
+ default:
+ break;
+ }
+ break;
}
+ *nmp = nm;
return 0;
Bad:
return 1;
@@ -1208,44 +1357,69 @@ static
Decl *
decl(Parser *p, Lexer *lx)
{
+ uint64 s;
Token t;
Decl *d;
- Dtor dt, *dtp;
- struct Decls **curr;
+ Expr *x;
+ Dtor *dt, *dt0;
+ struct Decls *ds;
alloc(d);
d->kind = 0;
d->pos.beg = lx->pos;
- if (spec(p, lx, &d->spec)) {
+ if (spec(p, lx, &s)) {
errorat(lx->pos, "invalid declaration specifier");
goto Bad;
}
- dtp = &dt;
- curr = &d->var.link;
-Dtor:
- if (dtor(p, lx, dtp, 0)) {
+
+ dt = getdtor(p);
+ dt0 = dt;
+ if (dtor(p, lx, dt, 0)) {
errorat(lx->pos, "invalid declarator");
goto Bad;
}
- t = peek(p, 0);
- if (t.kind == Aeq) {
+ x = nil;
+ ds = &d->vars;
+ d->spec = (uint32)s;
+
+ switch (t = peek(p, 0), t.kind) {
+ case Aeq:
t = advance(p, lx);
- d->kind = (d->kind != Dvars) ? Dvar : Dvars;
- d->var.init = expr(p, lx);
- }
- if (t.kind == Acomma) {
- d->kind = Dvars;
- alloc(*curr);
- dtp = &(*curr)->dtor;
- curr = &(*curr)->link;
- advance(p, lx);
- goto Dtor;
- }
+ x = expr(p, lx);
+ if (t.kind != Acomma) {
+ d->kind = Dvar;
+ d->init = x;
+ break;
+ }
+ /* fallthrough */
+ case Acomma:
+ d->kind = Dvars;
+ d->vars.init = x;
+ while (t.kind == Acomma) {
+ alloc(ds->link);
+ ds = ds->link;
+
+ t = advance(p, lx);
+ dt = getdtor(p);
+ if (dtor(p, lx, dt, 0)) {
+ errorat(lx->pos, "invalid declarator");
+ goto Bad;
+ }
+
+ t = peek(p, 0);
+ if (t.kind == Aeq) {
+ t = advance(p, lx);
+ ds->init = expr(p, lx);
+ }
+ }
+ break;
+
+ case Albrace:
+ d->kind = Dfunc;
+ alloc(d->body);
- t = peek(p, 0);
- if (t.kind == Albrace) {
if (!attop(p)) {
errorat(lx->pos, "nested function declarations");
goto Bad;
@@ -1255,21 +1429,25 @@ Dtor:
goto Bad;
}
- d->kind = Dfunc;
- alloc(d->func.body);
-
openscope(p);
- if (blkstmt(p, lx, &d->func.body)) {
+ if (blkstmt(p, lx, &d->body)) {
errorat(lx->pos, "failed to parse function body");
goto Bad;
}
closescope(p);
+
+ default:
+ ;
}
d->pos.end = lx->pos;
- declareobj(p, d);
+ // declareobj(p, d);
+ while (dt-- >= dt0)
+ putdtor(p);
return d;
Bad:
+ while (dt-- >= dt0)
+ putdtor(p);
errorat(lx->pos, "failed to parse top level declaration");
return nil;
}