diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/parse.c | 93 |
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; |
