aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff122
1 files changed, 89 insertions, 33 deletions
diff --git a/src/parse.cff b/src/parse.cff
index 13c89f5..34e7943 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -566,6 +566,8 @@ fn putdecl(P *Parser, eloc Loc, decl Decl) *Decl {
// Types Parsing //
///////////////////
+fn parsetype(P *Parser) *const Type;
+
fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type {
let loc = P.tokloc;
let tok Tok #?;
@@ -577,9 +579,10 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type
}
}
let ty = decl ? decl.u.Ty : interntype({ .u: :Agg { kind, name, id++ }});
- let agg = &(as(*Type)ty).u.Agg;
+ let ty = as(*Type)ty;
+ let agg = &ty.u.Agg;
- if name != #null and lexmatch(P, &tok, ';') {
+ if name != #null {
agg.fwd = #t;
if decl == #null {
decl = putdecl(P, loc, { name, loc, .u: :Ty(ty)});
@@ -587,11 +590,34 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type
*retdecl = decl;
}
}
- return ty;
- } else {
+ }
+ if !lexmatch(P, &tok, ';') {
agg.fwd = #f;
-
+ lexexpect(P, '{');
+ let size = 0, align = 1;
+ let flds Vec<AggField> = {};
+ while !lexmatch(P, #null, '}') {
+ let off = size;
+ let name = lexexpect(P, :ident).u.ident;
+ let type = parsetype(P);
+ if type {
+ off = ALIGNUP(off, type.align);
+ align = MAX(align, type.align);
+ size = kind == :Struct ? off + type.size
+ : MAX(size, type.size);
+ }
+ flds->push({ name, type, off });
+
+ if !lexmatch(P, #null, ',') {
+ lexexpect(P, '}');
+ break;
+ }
+ }
+ ty.size = size;
+ ty.align = align;
+ agg.flds = flds.dat[0::flds.len];
}
+ return ty;
}
fn xident2type(P *Parser, eloc Loc, name *const u8) *const Type {
@@ -605,15 +631,68 @@ fn xident2type(P *Parser, eloc Loc, name *const u8) *const Type {
return decl.u.Ty;
}
+fn parsefnparams(P *Parser, variadic *bool, paramnames *Vec<*const u8>, paramtys *Vec<*const Type>) void {
+ lexexpect(P, '(');
+ let tok Tok #?;
+ *variadic = #t;
+ while !lexmatch(P, &tok, ')') {
+ if lexmatch(P, #null, '...') {
+ *variadic = #t;
+ lexmatch(P, #null, ',');
+ lexexpect(P, ')');
+ break;
+ }
+ let name *const u8 = #null;
+ let type *const Type #?;
+ if lexmatch(P, &tok, :ident) {
+ let tok2 Tok #?;
+ if (tok2 = lexpeek(P)).t == ',' or tok2.t == ')' {
+ type = xident2type(P, tok.loc, tok.u.ident);
+ } else {
+ name = tok.u.ident;
+ type = parsetype(P);
+ }
+ } else {
+ type = parsetype(P);
+ }
+ if paramnames {
+ paramnames->push(name);
+ }
+ paramtys->push(type);
+ if !lexmatch(P, &tok, ',') {
+ lexexpect(P, ')');
+ break;
+ }
+ }
+}
+
+fn parsefntype(P *Parser) *const Type {
+ let variadic = #f;
+ let paramtys Vec<*const Type> = {};
+ parsefnparams(P, &variadic, #null, &paramtys);
+ let ret = parsetype(P);
+ return interntype({ .u: :Fn {
+ paramtys->move(P.alloc),
+ variadic,
+ ret,
+ }});
+}
+
fn parsetype(P *Parser) *const Type {
let tok Tok = {};
switch {
case lexmatch(P, &tok, :kw_const);
return constify(parsetype(P));
+
case lexmatch(P, &tok, '*');
return mkptrtype(parsetype(P));
+
case lexmatch(P, &tok, :ident);
return xident2type(P, tok.loc, tok.u.ident);
+
+ case lexmatch(P, &tok, :kw_fn);
+ return parsefntype(P);
+
case else;
fatal(P, tok.loc, "expected type (near %qT)", tok);
}
@@ -1252,34 +1331,7 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl {
paramnames Vec<*const u8> = {},
paramtys Vec<*const Type> = {};
- lexexpect(P, '(');
- while !lexmatch(P, &tok, ')') {
- if lexmatch(P, #null, '...') {
- Fn.variadic = #t;
- lexmatch(P, #null, ',');
- lexexpect(P, ')');
- break;
- }
- let name *const u8 = #null;
- let type *const Type #?;
- if lexmatch(P, &tok, :ident) {
- let tok2 Tok #?;
- if (tok2 = lexpeek(P)).t == ',' or tok2.t == ')' {
- type = xident2type(P, tok.loc, tok.u.ident);
- } else {
- name = tok.u.ident;
- type = parsetype(P);
- }
- } else {
- type = parsetype(P);
- }
- paramnames->push(name);
- paramtys->push(type);
- if !lexmatch(P, &tok, ',') {
- lexexpect(P, ')');
- break;
- }
- }
+ parsefnparams(P, &Fn.variadic, &paramnames, &paramtys);
Fn.paramnames = paramnames->move(P.alloc);
let retty = parsetype(P);
Fn.ty = interntype({ .size: 0, .align: 1, .u: :Fn {
@@ -1393,6 +1445,10 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void {
let name = lexexpect(P, :ident).u.ident;
parseagg(P, :Struct, name, &decl);
+ case lexmatch(P, &tok, :kw_union);
+ let name = lexexpect(P, :ident).u.ident;
+ parseagg(P, :Union, name, &decl);
+
case lexmatch(P, &tok, :kw_static);
struct Arg {
P *Parser,