about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-05-28 04:24:51 +0200
committerMel <mel@rnrd.eu>2026-05-28 04:24:51 +0200
commit4ec376b67d605910cb7757dc2e15a28a942f59ca (patch)
tree4e98614792e5a00175fa29e705142850993d68f6 /boot/parse.c
parenta5b24e3eedc8bd48de99cfb90abb3bececa5d29f (diff)
downloadcatskill-4ec376b67d605910cb7757dc2e15a28a942f59ca.tar.zst
catskill-4ec376b67d605910cb7757dc2e15a28a942f59ca.zip
Correct type modifier combinations and grouping
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 56d767a..ef71540 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -381,6 +381,8 @@ parser_block_node(struct Parser* p, struct Parser_Error* error)
         if (!parser_probe(p, TOKEN_CURLY_CLOSE))
             CHECK_RETURN(parser_end_statement(p, error), struct Tree_Block);
 
+        parser_unglue(p);
+
         if (!head) {
             head = statement;
         } else {
@@ -401,6 +403,7 @@ parser_block_node(struct Parser* p, struct Parser_Error* error)
 }
 
 struct Tree_Type* parser_node_type(struct Parser* p, struct Parser_Error* error);
+struct Tree_Type* parser_node_type_inner(struct Parser* p, struct Parser_Error* error);
 
 struct Tree_Function_Header
 parser_function_header_node(struct Parser* p, struct Parser_Error* error)
@@ -710,6 +713,11 @@ parser_node_type_tuple(struct Parser* p, struct Parser_Error* error)
     }
 
     struct Token close_token = CHECK(parser_need(p, TOKEN_ROUND_CLOSE, error));
+
+    // single-element tuples are equivalent to their inner type,
+    // which allows us to use them for grouping.
+    if (head && !head->next) return head;
+
     struct Span span = span_merge(open_token.span, close_token.span);
     return tree_type_new(
         TREE_TYPE_TUPLE, (union Tree_Type_Value){ .tuple = { head } }, span, open_token.location);
@@ -759,18 +767,31 @@ parser_node_type_array_or_map(struct Parser* p, struct Parser_Error* error)
 struct Tree_Type*
 parser_node_type_reference(struct Parser* p, struct Parser_Error* error)
 {
-    struct Token ampersand_token = CHECK(parser_need(p, TOKEN_AMPERSAND, error));
+    // we accept a fused `&&` token as two references
+    struct Token sigil = parser_next(p);
+    bool double_ref = token_is(&sigil, TOKEN_AND);
+    if (!double_ref && !token_is(&sigil, TOKEN_AMPERSAND)) {
+        parser_error(error, PARSER_ERROR_UNEXPECTED_TOKEN, sigil);
+        return nil;
+    }
 
-    struct Tree_Type* referenced_type = CHECK(parser_node_type(p, error));
+    struct Tree_Type* referenced_type = CHECK(parser_node_type_inner(p, error));
     if (!referenced_type) {
-        parser_error(error, PARSER_ERROR_EXPECTED_TYPE, ampersand_token);
+        parser_error(error, PARSER_ERROR_EXPECTED_TYPE, sigil);
         return nil;
     }
 
-    struct Span span = span_merge(ampersand_token.span, referenced_type->span);
-    return tree_type_new(
+    struct Span span = span_merge(sigil.span, referenced_type->span);
+    struct Tree_Type* ref = tree_type_new(
         TREE_TYPE_REFERENCE, (union Tree_Type_Value){ .reference = { referenced_type } }, span,
-        ampersand_token.location);
+        sigil.location);
+
+    if (double_ref) {
+        ref = tree_type_new(
+            TREE_TYPE_REFERENCE, (union Tree_Type_Value){ .reference = { ref } }, span,
+            sigil.location);
+    }
+    return ref;
 }
 
 struct Tree_Type*
@@ -793,6 +814,7 @@ parser_node_type_inner(struct Parser* p, struct Parser_Error* error)
     case TOKEN_SQUARE_OPEN:
         return parser_node_type_array_or_map(p, error);
     case TOKEN_AMPERSAND:
+    case TOKEN_AND:
         return parser_node_type_reference(p, error);
     default:
         parser_error(error, PARSER_ERROR_UNEXPECTED_TOKEN, token);