From af0c1d5ac3960776a4a485ca587744464630e634 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sun, 24 May 2020 08:06:34 -0700 Subject: contin: in the middle of reorganizing the declaration parsing. check-in before reorganizing keywords --- sys/cmd/cc/ast.c | 284 ++++++++++++++++++++++++++++++++++++++++++---------- sys/cmd/cc/cc.c | 9 +- sys/cmd/cc/cc.h | 53 +++++++--- sys/cmd/cc/rules.mk | 2 + sys/cmd/rules.mk | 3 + sys/libn/io.c | 2 + 6 files changed, 278 insertions(+), 75 deletions(-) (limited to 'sys') 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; } diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c index 16cc6e2..02ff773 100644 --- a/sys/cmd/cc/cc.c +++ b/sys/cmd/cc/cc.c @@ -201,7 +201,7 @@ initlx(Lexer *lx) { int i; - *lx = (Lexer){ 0 }; + memset(lx, 0, sizeof(*lx)); lx->b = lx->buf; /* predefine macros */ @@ -266,8 +266,8 @@ compile(byte *path) } } - initlx(&lx); initp(&p); + initlx(&lx); lx.io = openio(&lx, path); lx.pos = (Pos){ @@ -276,10 +276,7 @@ compile(byte *path) .col = 1, }; - Token t; - while (t = lex(&lx), t.kind != Aeof) - ; - // err = parse(&p, &lx); + err = parse(&p, &lx); freelx(&lx); return err; } diff --git a/sys/cmd/cc/cc.h b/sys/cmd/cc/cc.h index 7d30360..4b61346 100644 --- a/sys/cmd/cc/cc.h +++ b/sys/cmd/cc/cc.h @@ -373,10 +373,10 @@ enum Dvars, /* names (shouldn't interact with base AST node enumeration */ - Nident = iota(0), - Nparen = iota(1), - Nindex = iota(2), - Ncall = iota(3), + Nident, + Nparen, + Nindex, + Ncall, }; /* expressions */ @@ -561,23 +561,40 @@ struct Ptr Ptr *link; }; +struct Param +{ + uint32 qual; + Type *type; + string name; +}; + struct Name { - struct Node; + uint32 kind; union { string ident; struct Dtor *paren; - }; - union { - Expr *i; - Expr *p; + /* This is bloated ! */ + struct { + Name *name; + union { + struct { + uint32 q; + Expr *x; + } idx; + struct { + int n; + struct Param *arg; + } call; + }; + } sfx; }; }; struct Dtor { - Ptr ptr; - Name name; + Ptr ptr; + Name *name; }; struct Decls @@ -592,12 +609,16 @@ struct Decl { struct Node; uint32 spec; - string name; - Type *type; union { - Stmt *func; - Expr *init; - struct Decls *link; + struct { + string name; + Type *type; + union { + Stmt *body; + Expr *init; + }; + }; + struct Decls vars; }; }; diff --git a/sys/cmd/cc/rules.mk b/sys/cmd/cc/rules.mk index b32d5b6..2db1c56 100644 --- a/sys/cmd/cc/rules.mk +++ b/sys/cmd/cc/rules.mk @@ -5,8 +5,10 @@ include share/push.mk SRCS_$(d) := \ $(d)/pp.c \ $(d)/lex.c \ + $(d)/ast.c \ $(d)/cc.c + LIBS_$(d) := BINS_$(d) := $(d)/cc UNTS_$(d) := diff --git a/sys/cmd/rules.mk b/sys/cmd/rules.mk index a692dfa..4905a5f 100644 --- a/sys/cmd/rules.mk +++ b/sys/cmd/rules.mk @@ -8,4 +8,7 @@ include $(DIR)/rules.mk DIR := $(d)/cc include $(DIR)/rules.mk +DIR := $(d)/rc +include $(DIR)/rules.mk + include share/pop.mk diff --git a/sys/libn/io.c b/sys/libn/io.c index 3827a82..8aa4aa0 100644 --- a/sys/libn/io.c +++ b/sys/libn/io.c @@ -54,6 +54,8 @@ io·readln(Stream *s, int n, byte* buf) { byte* b; b = fgets(buf, n+1, s); + if (b == nil) + return -1; return strlen(buf); } -- cgit v1.2.1