Skip to content

Simplify arrow function parsing #360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 63 additions & 53 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -21245,12 +21245,10 @@ static __exception int js_parse_object_literal(JSParseState *s)
#define PF_IN_ACCEPTED (1 << 0)
/* allow function calls parsing in js_parse_postfix_expr() */
#define PF_POSTFIX_CALL (1 << 1)
/* allow arrow functions parsing in js_parse_postfix_expr() */
#define PF_ARROW_FUNC (1 << 2)
/* allow the exponentiation operator in js_parse_unary() */
#define PF_POW_ALLOWED (1 << 3)
#define PF_POW_ALLOWED (1 << 2)
/* forbid the exponentiation operator in js_parse_unary() */
#define PF_POW_FORBIDDEN (1 << 4)
#define PF_POW_FORBIDDEN (1 << 3)

static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);

Expand Down Expand Up @@ -22910,7 +22908,7 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
emit_label(s, label_next);
}

/* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */
/* allowed parse_flags: PF_POSTFIX_CALL */
static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
{
FuncCallType call_type;
Expand Down Expand Up @@ -22988,18 +22986,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
}
break;
case '(':
if ((parse_flags & PF_ARROW_FUNC) &&
js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
s->token.ptr,
s->token.line_num,
s->token.col_num))
return -1;
} else {
if (js_parse_expr_paren(s))
return -1;
}
if (js_parse_expr_paren(s))
return -1;
break;
case TOK_FUNCTION:
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
Expand Down Expand Up @@ -23041,16 +23029,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
if (s->token.u.ident.is_reserved) {
return js_parse_error_reserved_identifier(s);
}
if ((parse_flags & PF_ARROW_FUNC) &&
peek_token(s, TRUE) == TOK_ARROW) {
if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
s->token.ptr,
s->token.line_num,
s->token.col_num))
return -1;
} else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
peek_token(s, TRUE) != '\n') {
if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
peek_token(s, TRUE) != '\n') {
const uint8_t *source_ptr;
int source_line_num;
int source_col_num;
Expand All @@ -23067,17 +23047,6 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
source_line_num,
source_col_num))
return -1;
} else if ((parse_flags & PF_ARROW_FUNC) &&
((s->token.val == '(' &&
js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
peek_token(s, TRUE) == TOK_ARROW))) {
if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_ASYNC, JS_ATOM_NULL,
source_ptr,
source_line_num,
source_col_num))
return -1;
} else {
name = JS_DupAtom(s->ctx, JS_ATOM_async);
goto do_get_var;
Expand All @@ -23089,8 +23058,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return -1;
}
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
if (next_token(s)) /* update line number before emitting code */
if (next_token(s)) { /* update line number before emitting code */
JS_FreeAtom(s->ctx, name);
return -1;
}
do_get_var:
emit_op(s, OP_scope_get_var);
emit_u32(s, name);
Expand Down Expand Up @@ -23572,7 +23543,7 @@ static __exception int js_parse_delete(JSParseState *s)
return 0;
}

/* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */
/* allowed parse_flags: PF_POW_ALLOWED, PF_POW_FORBIDDEN */
static __exception int js_parse_unary(JSParseState *s, int parse_flags)
{
int op;
Expand Down Expand Up @@ -23662,8 +23633,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
parse_flags = 0;
break;
default:
if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) |
PF_POSTFIX_CALL))
if (js_parse_postfix_expr(s, PF_POSTFIX_CALL))
return -1;
if (!s->got_lf &&
(s->token.val == TOK_DEC || s->token.val == TOK_INC)) {
Expand Down Expand Up @@ -23699,15 +23669,14 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
return 0;
}

/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
/* allowed parse_flags: PF_IN_ACCEPTED */
static __exception int js_parse_expr_binary(JSParseState *s, int level,
int parse_flags)
{
int op, opcode;

if (level == 0) {
return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
PF_POW_ALLOWED);
return js_parse_unary(s, PF_POW_ALLOWED);
}
if (js_parse_expr_binary(s, level - 1, parse_flags))
return -1;
Expand Down Expand Up @@ -23834,14 +23803,14 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
}
if (next_token(s))
return -1;
if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC))
if (js_parse_expr_binary(s, level - 1, parse_flags))
return -1;
emit_op(s, opcode);
}
return 0;
}

/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
/* allowed parse_flags: PF_IN_ACCEPTED */
static __exception int js_parse_logical_and_or(JSParseState *s, int op,
int parse_flags)
{
Expand All @@ -23865,11 +23834,10 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
emit_op(s, OP_drop);

if (op == TOK_LAND) {
if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
} else {
if (js_parse_logical_and_or(s, TOK_LAND,
parse_flags & ~PF_ARROW_FUNC))
if (js_parse_logical_and_or(s, TOK_LAND, parse_flags))
return -1;
}
if (s->token.val != op) {
Expand Down Expand Up @@ -23901,7 +23869,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
emit_goto(s, OP_if_false, label1);
emit_op(s, OP_drop);

if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
break;
Expand All @@ -23911,7 +23879,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
return 0;
}

/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
/* allowed parse_flags: PF_IN_ACCEPTED */
static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
{
int label1, label2;
Expand Down Expand Up @@ -24090,12 +24058,54 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
emit_label(s, label_next);
}
return 0;
} else if (s->token.val == '(' &&
js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
s->token.ptr, s->token.line_num,
s->token.col_num);
} else if (token_is_pseudo_keyword(s, JS_ATOM_async)) {
const uint8_t *source_ptr;
int tok, source_line_num, source_col_num;
JSParsePos pos;

/* fast test */
tok = peek_token(s, TRUE);
if (tok == TOK_FUNCTION || tok == '\n')
goto next;

source_ptr = s->token.ptr;
source_line_num = s->token.line_num;
source_col_num = s->token.col_num;
js_parse_get_pos(s, &pos);
if (next_token(s))
return -1;
if ((s->token.val == '(' &&
js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
peek_token(s, TRUE) == TOK_ARROW)) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_ASYNC, JS_ATOM_NULL,
source_ptr, source_line_num,
source_col_num);
} else {
/* undo the token parsing */
if (js_parse_seek_token(s, &pos))
return -1;
}
} else if (s->token.val == TOK_IDENT &&
peek_token(s, TRUE) == TOK_ARROW) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
s->token.ptr, s->token.line_num,
s->token.col_num);
}
next:
if (s->token.val == TOK_IDENT) {
/* name0 is used to check for OP_set_name pattern, not duplicated */
name0 = s->token.u.ident.atom;
}
if (js_parse_cond_expr(s, parse_flags | PF_ARROW_FUNC))
if (js_parse_cond_expr(s, parse_flags))
return -1;

op = s->token.val;
Expand Down