diff options
Diffstat (limited to 'src/parse.cff')
| -rw-r--r-- | src/parse.cff | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/src/parse.cff b/src/parse.cff index 3453485..89a059f 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -634,6 +634,14 @@ typedef DeclYielder *fn(*Decl, *void) void; fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) void; fn parseenum(P *Parser, name *const u8, lax bool) *const Type { + let intty *const Type = #null; + let tok Tok #?; + if lexmatch(P, &tok, ':') { + intty = parsetype(P); + if !intty->is(:Int) { + fatal(P, tok.loc, "enum backing type must be integral (%t)", intty); + } + } lexexpect(P, '{'); let iota = 0i64; let max = iota; @@ -656,10 +664,10 @@ fn parseenum(P *Parser, name *const u8, lax bool) *const Type { break; } } - let intty *const Type = + let intty *const Type = intty ?? ( max < 1u64 << ((g_targ.intsize * 8) - 1) ? ty_int : max < 1u64 << 31 ? ty_i32 - : ty_i64; + : ty_i64); static id int = 0; return interntype({ .u: :Enum { intty, name, lax, id++, vals->move(P.alloc) }}); } @@ -1033,6 +1041,22 @@ fn parsetype(P *Parser) *const Type { case lexmatch(P, &tok, :kw_fn); return parsefntype(P); + case lexmatch(P, &tok, :kw_struct); + let decl *Decl; + return parseagg(P, tok.loc, :Struct, #null, &decl); + + case lexmatch(P, &tok, :kw_union); + let decl *Decl; + return parseagg(P, tok.loc, :Union, #null, &decl); + + case lexmatch(P, &tok, :kw_enum); + let decl *Decl; + if lexmatch(P, #null, :kw_union) { + return parseagg(P, tok.loc, :EUnion, #null, &decl); + } else { + return parseenum(P, #null, #{lax?} #f); + } + case else; fatal(P, tok.loc, "expected type (near %qT)", tok); } @@ -1388,7 +1412,7 @@ fn pexprimary(P *Parser) Expr { } fatal(P, tok.loc, "%t has no such variant %qT", ty, tok); } while #f; - ex = { tok.loc, ty, :EnumIni { name, i }}; + ex = { tok.loc, ty, :EnumIni(i) }; } else if ty->is(:Agg) and ty.u.Agg.kind == :EUnion { let name = (tok = lexexpects(P, :ident, "variant name")).u.ident; let fld = findaggfield(ty, name); @@ -2610,7 +2634,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) } } else { let name = lexexpect(P, :ident).u.ident; - let ty = parseenum(P, name, #{lax} #f); + let ty = parseenum(P, name, (attr & ATTR_LAX) != 0); decl = putdecl(P, loc, { name, loc, .u: :Ty(ty) }); } |