aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-05-24 08:06:34 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-05-24 08:06:34 -0700
commitaf0c1d5ac3960776a4a485ca587744464630e634 (patch)
tree11d53c335586cea8822af9f2fb2ff57027c9b095 /sys
parent39e4332d45e770dfe684071db4d3427fa2ca6b0c (diff)
contin: in the middle of reorganizing the declaration parsing. check-in before reorganizing keywords
Diffstat (limited to 'sys')
-rw-r--r--sys/cmd/cc/ast.c284
-rw-r--r--sys/cmd/cc/cc.c9
-rw-r--r--sys/cmd/cc/cc.h53
-rw-r--r--sys/cmd/cc/rules.mk2
-rw-r--r--sys/cmd/rules.mk3
-rw-r--r--sys/libn/io.c2
6 files changed, 278 insertions, 75 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;
}
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);
}