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.c167
1 files changed, 159 insertions, 8 deletions
diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c
index 49e35fd..0547712 100644
--- a/sys/cmd/cc/ast.c
+++ b/sys/cmd/cc/ast.c
@@ -17,15 +17,20 @@
// -----------------------------------------------------------------------
// helper functions
+static
string
nameof(Name *n)
{
- if (n->kind & Nident)
+ switch (n->kind) {
+ case Nident:
return n->ident;
- if (n->kind & Nparen)
+ case Nparen:
return nameof(n->paren->name);
-
- panicf("ill-formed declarator name");
+ case Nindex:
+ case Ncall:
+ return nameof(n->sfx.name);
+ }
+ panicf("unreachable");
}
static
@@ -201,8 +206,12 @@ nomatch(Token t, vlong kind)
static error spec(Parser *, Lexer *, uint64 *);
static error dtor(Parser *p, Lexer *lx, Dtor *d, int ab);
+static Type *typeofspec(Parser *, Lexer *, uint64 *);
+static Type *typeofdtor(Dtor *, Type *);
+
static Decl *decl(Parser *, Lexer *);
static Expr *expr(Parser *, Lexer *);
+
static error blkstmt(Parser *, Lexer *, Stmt **);
#define MAKEX(x, state) alloc((x)), (x)->kind = X##state
@@ -434,6 +443,7 @@ Bad:
return nil;
}
+#if 0
static
Type*
type(Parser *p, Lexer *lx)
@@ -462,6 +472,7 @@ Bad:
errorat(lx->pos, "failed to parse type expression");
return nil;
}
+#endif
static
Expr*
@@ -1006,12 +1017,115 @@ Bad:
// declarations
static
+Type *
+typeofname(Name *name, Type *type)
+{
+ switch (name->kind) {
+ case Nident:
+ return type;
+ case Nparen:
+ return typeofdtor(name->paren, type);
+ case Nindex:
+ return typeofname(name->sfx.name, array(type, name->sfx.idx.q, name->sfx.idx.x));
+ case Ncall:
+ return typeofname(name->sfx.name, func(type, name->sfx.call.n, name->sfx.call.arg, name->sfx.call.dots));
+ default:
+ panicf("unreachable");
+ }
+}
+
+static
+Type *
+typeofdtor(Dtor *decl, Type* type)
+{
+ int n;
+ Ptr *p;
+ uint64 b, tmp;
+
+ n = 0;
+ p = &decl->ptr;
+ b = p->kind;
+ while (b & 1) {
+ type = ptr(type, b >> 1);
+ if (++n >= 8) {
+ p = p->link;
+ b = p->kind;
+ } else {
+ b >>= 6;
+ }
+ }
+
+ return typeofname(decl->name, type);
+}
+
+static
+Type *
+aggr(Parser *p, Lexer *lx, string name, int kind)
+{
+ int n;
+ uint64 s;
+ Dtor *dt;
+ Token tk;
+ Type *t;
+ Type *fs[1024];
+ byte *nm[1024];
+ Expr *cx[1024];
+
+ n = -1;
+ for (;tk.kind != Arbrace && n < arrlen(fs); n++) {
+ t = typeofspec(p, lx, &s);
+
+ Field:
+ dt = getdtor(p);
+ dtor(p, lx, dt, 0);
+ fs[n] = typeofdtor(dt, t);
+ nm[n] = nameof(dt->name);
+ putdtor(p);
+
+ tk = peek(p, 0);
+ switch (tk.kind) {
+ case Acolon:
+ advance(p, lx);
+ cx[n] = expr(p, lx);
+ tk = peek(p, 0);
+ if (tk.kind == Asemi) {
+ tk = advance(p, lx);
+ continue;
+ }
+ if (tk.kind != Acomma) {
+ errorat(tk.pos, "unrecognized token %s in struct field declaration", tokens[tk.kind]);
+ goto Bad;
+ }
+ /* fallthrough */
+ case Acomma:
+ advance(p, lx);
+ n++;
+ goto Field;
+
+ case Asemi:
+ tk = advance(p, lx);
+ continue;
+
+ default:
+ errorat(tk.pos, "unrecognized token %s in struct field declaration", tokens[tk.kind]);
+ goto Bad;
+ }
+ }
+
+Bad:
+ errorat(tk.pos, "failed to parse aggregate declaration");
+ return nil;
+}
+
+static
error
spec(Parser *p, Lexer *lx, uint64 *spec)
{
Token t;
int n;
Sym *typ;
+ string name;
+ Type *tag;
uint64 s, sm;
s = 0;
@@ -1073,11 +1187,46 @@ spec(Parser *p, Lexer *lx, uint64 *spec)
errorat(lx->pos, "more than one base type specified");
goto Bad;
}
+ s += Bit(n);
break;
case Kstruct: case Kunion:
+ if (s & (Tstruct | Tunion)) {
+ errorat(lx->pos, "more than one aggregate type specified");
+ goto Bad;
+ }
+ s += Bit(n);
+ t = advance(p, lx);
+ if (t.kind != Aident && t.kind != Albrace) {
+ errorat(t.pos, "struct specifier missing valid declaration");
+ goto Bad;
+ }
+
+ name = nil;
+ tag = nil;
+ if (t.kind == Aident) {
+ name = t.val.s;
+ t = advance(p, lx);
+ }
+ if (t.kind == Albrace) {
+ t = advance(p, lx);
+ tag = aggr(p, lx, name, s & (Tstruct | Tunion));
+
+ if (nomatch(t, Arbrace)) {
+ errorat(t.pos, "invalid token %s in struct/union declaration", tokens[t.kind]);
+ goto Bad;
+ }
+ }
+ break;
+
case Kenum:
+ if (s & Tenum) {
+ errorat(lx->pos, "more than one enum type specifier found");
+ goto Bad;
+ }
+ s += Bit(n);
panicf("need to implement");
+ break;
default:
errorat(t.pos, "invalid keyword '%s' found in declaration specifier", keywords[n]);
@@ -1100,7 +1249,7 @@ Bad:
static
Type*
-typespec(Parser *p, Lexer *lx, uint64 *s)
+typeofspec(Parser *p, Lexer *lx, uint64 *s)
{
int n;
uint64 m;
@@ -1123,7 +1272,9 @@ typespec(Parser *p, Lexer *lx, uint64 *s)
}
return C.type.info + indextypespec[n];
}
- panicf("unreachable");
+
+ errorat(lx->pos, "invalid type specifier");
+ return nil;
}
@@ -1301,7 +1452,7 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab)
} while (t = peek(p, 0), t.kind == Acomma);
if (t.kind == Aellip) {
- nm->sfx.call.vararg = 1;
+ nm->sfx.call.dots = 1;
t = advance(p, lx);
}
@@ -1362,7 +1513,7 @@ Key:
switch (k = t.kind) {
case Akeywd:
if (Kconst <= k && k <= Katomic)
- ptr->kind |= Bit(n + (t.val.i - Kconst + 1));
+ ptr->kind |= Bit(6*n + (t.val.i - Kconst + 1));
else {
errorat(lx->pos, "invalid keyword '%s' modifies pointer", keywords[t.val.i]);
goto Bad;