diff --git a/source/quickjs.c b/source/quickjs.c index 74542323..2f6eff38 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -27980,6 +27980,7 @@ static cJSON *ast_parse_expr (ASTParseState *s); static cJSON *ast_parse_assign_expr (ASTParseState *s); static cJSON *ast_parse_statement (ASTParseState *s); static void ast_sync_to_statement (ASTParseState *s); +static cJSON *ast_parse_block_statements (ASTParseState *s); static cJSON *ast_parse_function_inner (ASTParseState *s, BOOL is_expr); static cJSON *ast_parse_arrow_function (ASTParseState *s); @@ -28925,6 +28926,63 @@ static cJSON *ast_parse_primary (ASTParseState *s) { ast_next_token (s); cJSON *right = ast_parse_assign_expr (s); cJSON_AddItemToObject (pair, "right", right); + } else if (s->token_val == '(') { + /* Method shorthand: init() {} => init: function init() {} */ + const uint8_t *fn_start = s->token_ptr; + cJSON *fn = ast_node (s, "function", fn_start); + + /* Set method name from property key */ + cJSON *left = cJSON_GetObjectItem (pair, "left"); + cJSON *name_item = cJSON_GetObjectItem (left, "name"); + if (name_item) + cJSON_AddStringToObject (fn, "name", name_item->valuestring); + + /* Parse parameters */ + cJSON *params = cJSON_AddArrayToObject (fn, "list"); + ast_next_token (s); /* skip '(' */ + while (s->token_val != ')' && s->token_val != TOK_EOF) { + if (s->token_val == TOK_IDENT) { + cJSON *param = ast_node (s, "name", s->token_ptr); + const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); + cJSON_AddStringToObject (param, "name", str ? str : ""); + JS_FreeCString (s->ctx, str); + ast_node_end (s, param, s->buf_ptr); + ast_next_token (s); + if (s->token_val == '=' || s->token_val == '|') { + ast_next_token (s); + cJSON *default_val = ast_parse_expr (s); + cJSON_AddItemToObject (param, "expression", default_val); + } + cJSON_AddItemToArray (params, param); + } else { + ast_error (s, s->token_ptr, "expected parameter name"); + break; + } + if (s->token_val == ',') ast_next_token (s); + else break; + } + if (s->token_val == ')') ast_next_token (s); + else if (s->token_val == TOK_EOF) + ast_error (s, s->token_ptr, "unterminated method parameter list"); + + if (cJSON_GetArraySize (params) > 4) + ast_error (s, s->token_ptr, "functions cannot have more than 4 parameters"); + + /* Parse body */ + if (s->token_val == '{') { + ast_next_token (s); + cJSON *stmts = ast_parse_block_statements (s); + cJSON_AddItemToObject (fn, "statements", stmts); + if (s->token_val == '}') ast_next_token (s); + else if (s->token_val == TOK_EOF) + ast_error (s, s->token_ptr, "unterminated method body"); + } else { + ast_error (s, s->token_ptr, "expected '{' for method body"); + } + + cJSON_AddNumberToObject (fn, "function_nr", s->function_nr++); + ast_node_end (s, fn, s->buf_ptr); + cJSON_AddItemToObject (pair, "right", fn); } else { ast_error (s, s->token_ptr, "expected ':' after property name"); }