aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-10 05:52:08 +0200
committerhachem <im@hachem.wtf>2026-09-10 05:52:08 +0200
commitd50af2e474281a1e88d191f783c2792824698974 (patch)
tree571afdff3ac141bbfcee37bc61dfdb6ea8fda163 /src/parser.c
parentbf157cf09b8b0888c54a165b887309a4e801f608 (diff)
feat: conditional select
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c
index 5379114..b0e049c 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -721,6 +721,43 @@ static bool parse_statement(struct Parser* parser, struct Statement* out)
if (value == NULL)
return false;
+ // conditional select: target = if_value if <cond> else else_value. The `if`
+ // must share the assignment's line, so a plain assignment followed by an
+ // `if` statement on the next line stays two statements.
+ if (op.type == TOKEN_EQUAL && !deref
+ && check(parser, TOKEN_IF) && parser->current.line == name.line)
+ {
+ advance_parser(parser);
+
+ struct Expr* left;
+ struct Token comparison;
+ struct Expr* right;
+ if (!parse_condition(parser, &left, &comparison, &right))
+ {
+ free_expr(value);
+ return false;
+ }
+
+ struct Expr* else_value = NULL;
+ if (!consume(parser, TOKEN_ELSE, "expected 'else' in conditional select")
+ || (else_value = parse_expression(parser)) == NULL)
+ {
+ free_expr(value);
+ free_expr(left);
+ free_expr(right);
+ return false;
+ }
+
+ out->kind = STATEMENT_SELECT;
+ out->select.target = name;
+ out->select.if_value = value;
+ out->select.left = left;
+ out->select.comparison = comparison;
+ out->select.right = right;
+ out->select.else_value = else_value;
+ return true;
+ }
+
out->kind = STATEMENT_ASSIGN;
out->assign.target_deref = deref;
out->assign.store_size = store_size;