From 37cd29c0299dc3a726c7f8273cf203a868133f57 Mon Sep 17 00:00:00 2001 From: lemon Date: Wed, 17 Aug 2022 12:21:57 +0200 Subject: struct,union --- src/parse.cff | 122 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 33 deletions(-) (limited to 'src/parse.cff') 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 = {}; + 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, ¶mtys); + 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, ¶mnames, ¶mtys); 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, -- cgit v1.2.3