about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-05-31 23:56:35 +0200
committerMel <mel@rnrd.eu>2025-05-31 23:56:35 +0200
commitef66c99536a631ff2bd1dab4a825ce16d2efa530 (patch)
treed1f2b12d53b3f670b694011f5b6a8077b92762f5 /boot/parse.c
parent43b8623ad8323ac73f40908f0fae9f57aa906f39 (diff)
downloadcatskill-ef66c99536a631ff2bd1dab4a825ce16d2efa530.tar.zst
catskill-ef66c99536a631ff2bd1dab4a825ce16d2efa530.zip
Parse blocks of statements as node
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 5d3b26c..5bfa006 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -9,6 +9,10 @@
     parse;           \
     if (!parser_error_is_none(error)) return nil;
 
+#define CHECK_RETURN(parse, ret) \
+    parse;                       \
+    if (!parser_error_is_none(error)) return (ret){ 0 };
+
 struct Parser_Error
 {
     enum Parser_Error_Kind
@@ -162,8 +166,52 @@ parser_probe(struct Parser* p, enum Token_Kind kind)
     return token_is(&token, kind);
 }
 
+struct Statement* parser_statement(struct Parser* p, struct Parser_Error* error);
 struct Expression* parser_expression(struct Parser* p, struct Parser_Error* error);
 
+void
+parser_end_statement(struct Parser* p, struct Parser_Error* error)
+{
+    struct Token token = parser_peek(p);
+    if (!token_ends_statement(&token)) {
+        *error = parser_error(PARSER_ERROR_EXPECTED_STATEMENT_END);
+        return;
+    }
+    parser_next(p);
+}
+
+struct Block_Node
+parser_block_node(struct Parser* p, struct Parser_Error* error)
+{
+    struct Token start_token =
+        CHECK_RETURN(parser_need(p, TOKEN_CURLY_OPEN, error), struct Block_Node);
+
+    struct Statement* head = nil;
+    struct Statement* current = nil;
+
+    while (!parser_probe(p, TOKEN_CURLY_CLOSE)) {
+        struct Statement* statement = CHECK_RETURN(parser_statement(p, error), struct Block_Node);
+        CHECK_RETURN(parser_end_statement(p, error), struct Block_Node);
+
+        if (!head) {
+            head = statement;
+        } else {
+            current->next = statement;
+        }
+        current = statement;
+    }
+
+    struct Token end_token =
+        CHECK_RETURN(parser_need(p, TOKEN_CURLY_CLOSE, error), struct Block_Node);
+    struct Span span = span_merge(start_token.span, end_token.span);
+
+    return (struct Block_Node){
+        .statements = head,
+        .span = span,
+        .location = start_token.location,
+    };
+}
+
 struct Type_Node
 parser_node_type(struct Parser* p, struct Parser_Error* error)
 {
@@ -482,17 +530,6 @@ parser_statement_declaration(struct Parser* p, struct Parser_Error* error)
     return statement_new(STATEMENT_DECLARATION, value, span, location);
 }
 
-void
-parser_end_statement(struct Parser* p, struct Parser_Error* error)
-{
-    struct Token token = parser_peek(p);
-    if (!token_ends_statement(&token)) {
-        *error = parser_error(PARSER_ERROR_EXPECTED_STATEMENT_END);
-        return;
-    }
-    parser_next(p);
-}
-
 struct Statement*
 parser_statement(struct Parser* p, struct Parser_Error* error)
 {
@@ -504,7 +541,7 @@ parser_statement(struct Parser* p, struct Parser_Error* error)
         token = parser_peek(p);
     }
 
-    if (token.kind == TOKEN_NAME) {
+    if (token_is(&token, TOKEN_NAME)) {
         // NOTE: these can be a variable declaration:
         //     x uint = 123
         //     me, them Obj = create()
@@ -516,6 +553,14 @@ parser_statement(struct Parser* p, struct Parser_Error* error)
             return parser_statement_declaration(p, error);
     }
 
+    if (token_is(&token, TOKEN_CURLY_OPEN)) {
+        // a block statement.
+        struct Block_Node block = CHECK(parser_block_node(p, error));
+        return statement_new(
+            STATEMENT_BLOCK, (union Statement_Value){ .block = { block } }, block.span,
+            block.location);
+    }
+
     struct Expression* expression = CHECK(parser_expression(p, error));
 
     // expand by one byte to include the statement terminator.
@@ -533,11 +578,8 @@ parser_do_your_thing(struct Parser* p, struct Parser_Error* error)
 
     struct Statement* current = nil;
     while (!p->lexer->eof) {
-        struct Statement* next = parser_statement(p, error);
-        if (!parser_error_is_none(error)) return (struct Tree){ nil };
-
-        parser_end_statement(p, error);
-        if (!parser_error_is_none(error)) return (struct Tree){ nil };
+        struct Statement* next = CHECK_RETURN(parser_statement(p, error), struct Tree);
+        CHECK_RETURN(parser_end_statement(p, error), struct Tree);
 
         if (current) {
             current->next = next;
@@ -551,4 +593,5 @@ parser_do_your_thing(struct Parser* p, struct Parser_Error* error)
     return (struct Tree){ head };
 }
 
-#undef CHECK
\ No newline at end of file
+#undef CHECK
+#undef CHECK_RETURN
\ No newline at end of file