aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/parse.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-15 14:52:15 +0200
committerlemon <lsof@mailbox.org>2022-08-15 14:52:15 +0200
commitfeeb86d046d55d197040c7061e39198c80373ecb (patch)
tree733d4da08ec979eb8f6b9b91d39c655e7fd4847b /bootstrap/parse.c
parentf906d0b350b0b4ceb747669c9a9845d11bd0e486 (diff)
#when
Diffstat (limited to 'bootstrap/parse.c')
-rw-r--r--bootstrap/parse.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 0d9ab16..1848caf 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -394,6 +394,8 @@ lex(struct parser *P) {
tok.t = '##';
} else if (!strcmp(s, "#len")) {
tok.t = '#len';
+ } else if (!strcmp(s, "#when")) {
+ tok.t = TKhwhen;
} else if (!strcmp(s, "#tag")) {
tok.t = '#tag';
} else if (!strcmp(s, "#?")) {
@@ -3073,6 +3075,31 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) {
struct attr attr = {0};
decl.container = P->container;
+ while (lexmatch(P, &tok, TKhwhen)) {
+ struct expr test = parseexpr(P);
+ if (!fold(&test) || test.ty->t != TYbool)
+ fatal(P, test.span, "#when test is not a constant bool expression");
+ assert(test.t == Eboolit);
+ lexexpect(P, '{');
+ if (test.i) {
+ while (!lexmatch(P, &tok, '}'))
+ parsedecl(yield, yarg, P, toplevel);
+ } else {
+ int pabal = 0, // ( ) parens balance
+ bkbal = 0, // [ ] brackets ..
+ bcbal = 1; // { } braces ..
+
+ while (pabal || bkbal || bcbal) {
+ tok = lex(P);
+ switch (tok.t) {
+ case '[': ++bkbal; break; case ']': --bkbal; break;
+ case '{': ++bcbal; break; case '}': --bcbal; break;
+ case '(': ++pabal; break; case ')': --pabal; break;
+ }
+ }
+ }
+ }
+
if (lexmatch(P, &tok, '#')) {
lexexpect(P, '[');
while (!lexmatch(P, NULL, ']')) {