about summary refs log tree commit diff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/parse.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 658a522..490995f 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -335,16 +335,11 @@ parser_node_type_structure(struct Parser* p, struct Parser_Error* error)
 
     parser_unglue(p);
 
-    struct Type_Node* head = nil;
-    struct Type_Node* current = nil;
+    struct Type_Node *head = nil, *current = nil;
     while (!parser_probe(p, TOKEN_CURLY_CLOSE)) {
         struct Token field_name_token = CHECK(parser_need(p, TOKEN_NAME, error));
 
         struct Type_Node* field_type = CHECK(parser_node_type(p, error));
-        if (!field_type) {
-            *error = parser_error(PARSER_ERROR_EXPECTED_TYPE);
-            return nil;
-        }
         field_type->value_name = field_name_token.value.name;
 
         if (!head)
@@ -369,8 +364,48 @@ parser_node_type_structure(struct Parser* p, struct Parser_Error* error)
 struct Type_Node*
 parser_node_type_variant(struct Parser* p, struct Parser_Error* error)
 {
-    // TODO
-    return nil;
+    struct Token variant_token = CHECK(parser_need(p, TOKEN_WORD_VARIANT, error));
+    CHECK(parser_need(p, TOKEN_CURLY_OPEN, error));
+
+    parser_unglue(p);
+
+    struct Type_Node *head = nil, *current = nil;
+    while (!parser_probe(p, TOKEN_CURLY_CLOSE)) {
+        struct Token variant_name_token = CHECK(parser_need(p, TOKEN_NAME, error));
+        struct String variant_name = variant_name_token.value.name;
+
+        struct Type_Node* backing_type = nil;
+
+        struct Token next = parser_peek(p);
+        bool has_backing_type =
+            !token_is(&next, TOKEN_NEWLINE) && !token_is(&next, TOKEN_COMMA)
+            && !token_is(&next, TOKEN_CURLY_CLOSE);
+
+        if (has_backing_type) {
+            backing_type = CHECK(parser_node_type(p, error));
+        } else {
+            backing_type = type_node_none(variant_name_token.span, variant_name_token.location);
+        }
+
+        backing_type->value_name = variant_name;
+        if (!head)
+            head = backing_type;
+        else
+            current->next = backing_type;
+        current = backing_type;
+
+        next = parser_peek(p);
+        if (token_is(&next, TOKEN_COMMA) || token_is(&next, TOKEN_NEWLINE)) parser_next(p);
+    }
+
+    parser_unglue(p);
+
+    struct Token close_token = CHECK(parser_need(p, TOKEN_CURLY_CLOSE, error));
+    struct Span span = span_merge(variant_token.span, close_token.span);
+
+    return type_node_new(
+        TYPE_NODE_VARIANT, (union Type_Node_Value){ .variant = { head } }, span,
+        variant_token.location);
 }
 
 struct Type_Node*
@@ -388,8 +423,39 @@ parser_node_type_function(struct Parser* p, struct Parser_Error* error)
 struct Type_Node*
 parser_node_type_class(struct Parser* p, struct Parser_Error* error)
 {
-    // TODO
-    return nil;
+    struct Token class_token = CHECK(parser_need(p, TOKEN_WORD_CLASS, error));
+    CHECK(parser_need(p, TOKEN_CURLY_OPEN, error));
+
+    parser_unglue(p);
+
+    struct Type_Node *head = nil, *current = nil;
+    while (!parser_probe(p, TOKEN_CURLY_CLOSE)) {
+        struct Token method_name_token = CHECK(parser_need(p, TOKEN_NAME, error));
+        struct String method_name = method_name_token.value.name;
+
+        struct Function_Header_Node header = CHECK(parser_function_header_node(p, error));
+        // allocate a new type node for the method type,
+        // for the sake of consistency and the built-in type node linked list.
+        struct Type_Node* method_type = type_node_new(
+            TYPE_NODE_FUNCTION, (union Type_Node_Value){ .function = { header } }, header.span,
+            header.parameters_type_and_name->location);
+        method_type->value_name = method_name;
+
+        if (!head)
+            head = method_type;
+        else
+            current->next = method_type;
+        current = method_type;
+
+        if (parser_probe(p, TOKEN_COMMA) || parser_probe(p, TOKEN_NEWLINE)) parser_next(p);
+    }
+
+    parser_unglue(p);
+
+    struct Token close_token = CHECK(parser_need(p, TOKEN_CURLY_CLOSE, error));
+    struct Span span = span_merge(class_token.span, close_token.span);
+    return type_node_new(
+        TYPE_NODE_CLASS, (union Type_Node_Value){ .class = { head } }, span, class_token.location);
 }
 
 struct Type_Node*
@@ -397,14 +463,9 @@ parser_node_type_tuple(struct Parser* p, struct Parser_Error* error)
 {
     struct Token open_token = CHECK(parser_need(p, TOKEN_ROUND_OPEN, error));
 
-    struct Type_Node* head = nil;
-    struct Type_Node* current = nil;
+    struct Type_Node *head = nil, *current = nil;
     while (!parser_probe(p, TOKEN_ROUND_CLOSE)) {
         struct Type_Node* type = CHECK(parser_node_type(p, error));
-        if (!type) {
-            *error = parser_error(PARSER_ERROR_EXPECTED_TYPE);
-            return nil;
-        }
 
         if (!head)
             head = type;