Simplify arrow function parsing (#360)
- parse arrow functions only in `js_parse_cond_expr` - remove `PF_ARROW_FUNC` flag and simplify parsing functions with flags
This commit is contained in:
parent
16e7661fa0
commit
4fb2e38b8a
1 changed files with 63 additions and 53 deletions
110
quickjs.c
110
quickjs.c
|
@ -21260,12 +21260,10 @@ static __exception int js_parse_object_literal(JSParseState *s)
|
||||||
#define PF_IN_ACCEPTED (1 << 0)
|
#define PF_IN_ACCEPTED (1 << 0)
|
||||||
/* allow function calls parsing in js_parse_postfix_expr() */
|
/* allow function calls parsing in js_parse_postfix_expr() */
|
||||||
#define PF_POSTFIX_CALL (1 << 1)
|
#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() */
|
/* 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() */
|
/* 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);
|
static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
|
||||||
|
|
||||||
|
@ -22925,7 +22923,7 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
|
||||||
emit_label(s, label_next);
|
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)
|
static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
||||||
{
|
{
|
||||||
FuncCallType call_type;
|
FuncCallType call_type;
|
||||||
|
@ -23003,18 +23001,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '(':
|
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))
|
if (js_parse_expr_paren(s))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TOK_FUNCTION:
|
case TOK_FUNCTION:
|
||||||
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
|
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
|
||||||
|
@ -23056,15 +23044,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
||||||
if (s->token.u.ident.is_reserved) {
|
if (s->token.u.ident.is_reserved) {
|
||||||
return js_parse_error_reserved_identifier(s);
|
return js_parse_error_reserved_identifier(s);
|
||||||
}
|
}
|
||||||
if ((parse_flags & PF_ARROW_FUNC) &&
|
if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
|
||||||
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') {
|
peek_token(s, TRUE) != '\n') {
|
||||||
const uint8_t *source_ptr;
|
const uint8_t *source_ptr;
|
||||||
int source_line_num;
|
int source_line_num;
|
||||||
|
@ -23082,17 +23062,6 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
||||||
source_line_num,
|
source_line_num,
|
||||||
source_col_num))
|
source_col_num))
|
||||||
return -1;
|
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 {
|
} else {
|
||||||
name = JS_DupAtom(s->ctx, JS_ATOM_async);
|
name = JS_DupAtom(s->ctx, JS_ATOM_async);
|
||||||
goto do_get_var;
|
goto do_get_var;
|
||||||
|
@ -23104,8 +23073,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
|
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;
|
return -1;
|
||||||
|
}
|
||||||
do_get_var:
|
do_get_var:
|
||||||
emit_op(s, OP_scope_get_var);
|
emit_op(s, OP_scope_get_var);
|
||||||
emit_u32(s, name);
|
emit_u32(s, name);
|
||||||
|
@ -23587,7 +23558,7 @@ static __exception int js_parse_delete(JSParseState *s)
|
||||||
return 0;
|
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)
|
static __exception int js_parse_unary(JSParseState *s, int parse_flags)
|
||||||
{
|
{
|
||||||
int op;
|
int op;
|
||||||
|
@ -23677,8 +23648,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
|
||||||
parse_flags = 0;
|
parse_flags = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) |
|
if (js_parse_postfix_expr(s, PF_POSTFIX_CALL))
|
||||||
PF_POSTFIX_CALL))
|
|
||||||
return -1;
|
return -1;
|
||||||
if (!s->got_lf &&
|
if (!s->got_lf &&
|
||||||
(s->token.val == TOK_DEC || s->token.val == TOK_INC)) {
|
(s->token.val == TOK_DEC || s->token.val == TOK_INC)) {
|
||||||
|
@ -23714,15 +23684,14 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
|
||||||
return 0;
|
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,
|
static __exception int js_parse_expr_binary(JSParseState *s, int level,
|
||||||
int parse_flags)
|
int parse_flags)
|
||||||
{
|
{
|
||||||
int op, opcode;
|
int op, opcode;
|
||||||
|
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
|
return js_parse_unary(s, PF_POW_ALLOWED);
|
||||||
PF_POW_ALLOWED);
|
|
||||||
}
|
}
|
||||||
if (js_parse_expr_binary(s, level - 1, parse_flags))
|
if (js_parse_expr_binary(s, level - 1, parse_flags))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -23849,14 +23818,14 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
|
||||||
}
|
}
|
||||||
if (next_token(s))
|
if (next_token(s))
|
||||||
return -1;
|
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;
|
return -1;
|
||||||
emit_op(s, opcode);
|
emit_op(s, opcode);
|
||||||
}
|
}
|
||||||
return 0;
|
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,
|
static __exception int js_parse_logical_and_or(JSParseState *s, int op,
|
||||||
int parse_flags)
|
int parse_flags)
|
||||||
{
|
{
|
||||||
|
@ -23880,11 +23849,10 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
|
||||||
emit_op(s, OP_drop);
|
emit_op(s, OP_drop);
|
||||||
|
|
||||||
if (op == TOK_LAND) {
|
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;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
if (js_parse_logical_and_or(s, TOK_LAND,
|
if (js_parse_logical_and_or(s, TOK_LAND, parse_flags))
|
||||||
parse_flags & ~PF_ARROW_FUNC))
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (s->token.val != op) {
|
if (s->token.val != op) {
|
||||||
|
@ -23916,7 +23884,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
|
||||||
emit_goto(s, OP_if_false, label1);
|
emit_goto(s, OP_if_false, label1);
|
||||||
emit_op(s, OP_drop);
|
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;
|
return -1;
|
||||||
if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
|
if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
|
||||||
break;
|
break;
|
||||||
|
@ -23926,7 +23894,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
|
||||||
return 0;
|
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)
|
static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
|
||||||
{
|
{
|
||||||
int label1, label2;
|
int label1, label2;
|
||||||
|
@ -24105,12 +24073,54 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
|
||||||
emit_label(s, label_next);
|
emit_label(s, label_next);
|
||||||
}
|
}
|
||||||
return 0;
|
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) {
|
if (s->token.val == TOK_IDENT) {
|
||||||
/* name0 is used to check for OP_set_name pattern, not duplicated */
|
/* name0 is used to check for OP_set_name pattern, not duplicated */
|
||||||
name0 = s->token.u.ident.atom;
|
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;
|
return -1;
|
||||||
|
|
||||||
op = s->token.val;
|
op = s->token.val;
|
||||||
|
|
Loading…
Reference in a new issue