about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-06-01 00:47:39 +0200
committerMel <mel@rnrd.eu>2025-06-01 00:47:39 +0200
commitcea333644191567bcfdd1e24e4606aafbf34e3cb (patch)
tree42d50d37059a7f23cd659823fb3fba7695c83615 /boot/parse.c
parentef66c99536a631ff2bd1dab4a825ce16d2efa530 (diff)
downloadcatskill-cea333644191567bcfdd1e24e4606aafbf34e3cb.tar.zst
catskill-cea333644191567bcfdd1e24e4606aafbf34e3cb.zip
Parse if/else if/else statements
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 5bfa006..ed00f94 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -531,6 +531,55 @@ parser_statement_declaration(struct Parser* p, struct Parser_Error* error)
 }
 
 struct Statement*
+parser_statement_conditional(struct Parser* p, struct Parser_Error* error)
+{
+    struct Statement_Value_Conditional conditional = { 0 };
+    struct Token if_token = parser_need(p, TOKEN_WORD_IF, error);
+
+    // primary if condition + block.
+    struct Expression* if_condition = CHECK(parser_expression(p, error));
+    struct Block_Node then_block = CHECK(parser_block_node(p, error));
+    conditional.conditions[conditional.condition_count++] = (struct Statement_Conditional_Branch){
+        .when = if_condition,
+        .then = then_block,
+    };
+
+    struct Span span = span_merge(if_token.span, then_block.span);
+    while (parser_probe(p, TOKEN_WORD_ELSE)) {
+        check(conditional.condition_count < STATEMENT_VALUE_CONDITIONAL_MAX,
+              "too many conditional branches");
+        parser_next(p);
+
+        struct Statement_Conditional_Branch branch = { 0 };
+        if (parser_probe(p, TOKEN_WORD_IF)) {
+            // else if condition + block.
+            parser_next(p);
+            struct Expression* else_condition = CHECK(parser_expression(p, error));
+            struct Block_Node else_block = CHECK(parser_block_node(p, error));
+
+            branch = (struct Statement_Conditional_Branch){
+                .when = else_condition,
+                .then = else_block,
+            };
+        } else {
+            // else block.
+            struct Block_Node else_block = CHECK(parser_block_node(p, error));
+            branch = (struct Statement_Conditional_Branch){
+                .when = nil,
+                .then = else_block,
+            };
+        }
+
+        conditional.conditions[conditional.condition_count++] = branch;
+        span = span_merge(span, branch.then.span);
+    }
+
+    return statement_new(
+        STATEMENT_CONDITIONAL, (union Statement_Value){ .conditional = conditional }, span,
+        if_token.location);
+}
+
+struct Statement*
 parser_statement(struct Parser* p, struct Parser_Error* error)
 {
     struct Token token = parser_peek(p);
@@ -553,6 +602,8 @@ parser_statement(struct Parser* p, struct Parser_Error* error)
             return parser_statement_declaration(p, error);
     }
 
+    if (token_is(&token, TOKEN_WORD_IF)) return parser_statement_conditional(p, error);
+
     if (token_is(&token, TOKEN_CURLY_OPEN)) {
         // a block statement.
         struct Block_Node block = CHECK(parser_block_node(p, error));