diff options
Diffstat (limited to 'boot/parse.c')
| -rw-r--r-- | boot/parse.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/boot/parse.c b/boot/parse.c index 3d2706f..ac324f9 100644 --- a/boot/parse.c +++ b/boot/parse.c @@ -705,7 +705,7 @@ parser_expression_member(struct Parser* p, struct Parser_Error* error) { struct Expression* left = CHECK(parser_expression_primary(p, error)); - // NOTE: see `parser_expression_postfix_call`. + // NOTE: see `parser_expression_postfix_call_or_construct`. while (parser_probe(p, TOKEN_DOT)) { parser_next(p); struct Token name_token = CHECK(parser_need(p, TOKEN_NAME, error)); @@ -720,31 +720,53 @@ parser_expression_member(struct Parser* p, struct Parser_Error* error) } struct Expression* -parser_expression_postfix_call( +parser_expression_postfix_call_or_construct( struct Parser* p, struct Expression* subject, struct Parser_Error* error) { // NOTE: because of the way the parser works, we have to parse all subsequent - // call expressions in the same loop. + // call/construct expressions in the same loop. // this is the case with an expression like `meow_function()(123)`, // where the hypothetical `meow_function` returns a function pointer. + + // calls and constructs look identical in the parser. + // * call: `meow_function(123, "hello")` + // * construct: `Meow(num = 123, str = "hello")` while (parser_probe(p, TOKEN_ROUND_OPEN)) { parser_next(p); + struct String_Array argument_names = string_array_new(); struct Expression *arguments_head = nil, *arguments_current = nil; while (!parser_probe(p, TOKEN_ROUND_CLOSE)) { + + // check if we have a named argument. + struct String name = string_empty(); + struct Token name_token = parser_peek(p), next = parser_peek_further(p); + if (token_is(&name_token, TOKEN_NAME) && token_is(&next, TOKEN_ASSIGN)) { + parser_next(p); + parser_next(p); + name = name_token.value.name; + } + struct Expression* argument = CHECK(parser_expression(p, error)); if (!arguments_head) arguments_head = argument; else arguments_current->next = argument; arguments_current = argument; + + // if we have a named argument, we need to add it to the names array, + // otherwise we just add an empty string. + string_array_add(&argument_names, name); + if (parser_probe(p, TOKEN_COMMA)) parser_next(p); } struct Token token = CHECK(parser_need(p, TOKEN_ROUND_CLOSE, error)); struct Span span = span_merge(subject->span, token.span); - union Expression_Value value = { .call = { subject, arguments_head } }; - subject = expression_new(EXPRESSION_CALL, value, span, token.location); + union Expression_Value value = { + .call_or_construct = { subject, arguments_head, argument_names } + }; + subject = expression_new(EXPRESSION_CALL_OR_CONSTRUCT, value, span, token.location); } return subject; @@ -754,7 +776,7 @@ struct Expression* parser_expression_postfix_subscript( struct Parser* p, struct Expression* subject, struct Parser_Error* error) { - // NOTE: see `parser_expression_postfix_call`. + // NOTE: see `parser_expression_postfix_call_or_construct`. while (parser_probe(p, TOKEN_SQUARE_OPEN)) { parser_next(p); @@ -776,7 +798,7 @@ parser_expression_postfix(struct Parser* p, struct Parser_Error* error) struct Token token = parser_peek(p); switch (token.kind) { case TOKEN_ROUND_OPEN: - return parser_expression_postfix_call(p, expression, error); + return parser_expression_postfix_call_or_construct(p, expression, error); case TOKEN_SQUARE_OPEN: return parser_expression_postfix_subscript(p, expression, error); default:; |
