aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/parse.cff b/src/parse.cff
index dbc8e29..ffe9a9d 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -827,6 +827,15 @@ fn findaggfield(ty *const Type, name *const u8) *AggField {
return #null;
}
+fn findbitffield(ty *const Type, name *const u8) *BitFField {
+ foreach_ptr(fld, i, ty.u.BitF.flds) {
+ if streq(fld.name, name) {
+ return fld;
+ }
+ }
+ return #null;
+}
+
fn parsebitfield(P *Parser, name *const u8) *const Type {
let ty Type = { .u: :BitF{} };
let bitf = &ty.u.BitF;
@@ -1246,6 +1255,43 @@ fn parsearrini(P *Parser, loc Loc, ty *const Type) Expr {
return { loc, ty, :ArrIni { idxs->move(P.alloc), exs->move(P.alloc), maxn }};
}
+fn parsebitfini(P *Parser, loc Loc, ty *const Type) Expr {
+ let loc = loc;
+ let tok Tok #?;
+ let flds Vec<*const BitFField> = {};
+ let exs Vec<Expr> = {};
+ let iota = 0u64;
+ while !lexmatch(P, &tok, '}') {
+ let fld *BitFField #?;
+ let ex Expr #?;
+ if lexmatch(P, &tok, '.') {
+ fld = findbitffield(ty, (tok = lexexpects(P, :ident, "field name")).u.ident);
+ lexexpect(P, ':');
+ if fld == #null {
+ fatal(P, tok.loc, "%t has no such field %qT", ty, &tok);
+ }
+ iota = (fld - ty.u.BitF.flds.#ptr) + 1;
+ } else {
+ if iota >= ty.u.BitF.flds.#len {
+ fatal(P, tok.loc, "excess elements in %t struct initializer", ty);
+ }
+ fld = &ty.u.BitF.flds[iota++];
+ }
+ P.targty = fld.ty;
+ ex = parseexpr(P);
+ if !typematchestarg(fld.ty, ex.ty) {
+ err(P, ex.loc, "incompatible element `%s' type in %t initializer (%t, expected %t)",
+ fld.name, ty, ex.ty, fld.ty);
+ }
+ flds->push(fld);
+ exs->push(ex);
+ if !lexmatch(P, &tok, ',') {
+ lexexpects(P, '}', "`,' or `}'");
+ break;
+ }
+ }
+ return { loc, ty, :BitFIni { flds->move(P.alloc), exs->move(P.alloc) }};
+}
fn mergetoktrees(alloc *Allocator, src *[#]Tok, n int) [#]Tok {
let total = 0z;
@@ -1412,7 +1458,7 @@ fn pexprimary(P *Parser) Expr {
fatal(P, tok.loc, "%t has no such decl %qT", ty, &tok);
}
continue;
- } else if !ty->is(:Agg) and !ty->is(:Enum) {
+ } else if !ty->is(:Agg) and !ty->is(:Enum) and !ty->is(:BitF) {
fatal(P, tok.loc, "type is not aggregate or enum");
} else {;
P.targty = ty;
@@ -1500,7 +1546,7 @@ fn pexprimary(P *Parser) Expr {
let off = 0z;
for ;; {
let name = (tok = lexexpect(P, :ident)).u.ident;
- let fld = findaggfield(ty, name);
+ let fld *AggField = ty->is(:Agg) ? findaggfield(ty, name) : #null;
if fld == #null {
fatal(P, tok.loc, "%t has no such field %qT", ty, &tok);
}
@@ -1585,6 +1631,8 @@ fn pexprimary(P *Parser) Expr {
ex = parseaggini(P, tok.loc, ty);
} else if ty->is(:Arr) {
ex = parsearrini(P, tok.loc, ty);
+ } else if ty->is(:BitF) {
+ ex = parsebitfini(P, tok.loc, ty);
} else {
fatal(P, tok.loc, "excess elements in initializer");
}