Browse Source

Fixes to RegExp vs. division lexing

pull/1779/head
Sami Vaarala 7 years ago
parent
commit
4cf68c86f7
  1. 84
      src-input/duk_js_compiler.c
  2. 1
      src-input/duk_js_compiler.h

84
src-input/duk_js_compiler.c

@ -235,9 +235,9 @@ DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *
DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after);
DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token);
DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token);
DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
@ -463,6 +463,10 @@ DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t e
comp_ctx->curr_func.reject_regexp_in_adv = 0;
regexp = 0;
}
if (comp_ctx->curr_func.allow_regexp_in_adv) {
comp_ctx->curr_func.allow_regexp_in_adv = 0;
regexp = 1;
}
if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
@ -3231,7 +3235,7 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
#endif
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
duk__advance(comp_ctx);
duk__advance(comp_ctx); /* No RegExp after object literal. */
duk__ivalue_regconst(res, st.reg_obj);
return;
@ -3281,7 +3285,7 @@ DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue
}
/* eat the right paren */
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */
DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
@ -3414,7 +3418,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* No RegExp after parenthesized expression. */
comp_ctx->curr_func.allow_in = prev_allow_in;
comp_ctx->curr_func.paren_level--;
return;
@ -5344,7 +5348,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
}
DUK__SETTEMP(comp_ctx, temp_reset);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
comp_ctx->curr_func.allow_regexp_in_adv = 1;
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
pc_l3 = duk__get_current_pc(comp_ctx);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@ -5435,7 +5440,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
DUK__SETTEMP(comp_ctx, temp_reset);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
comp_ctx->curr_func.allow_regexp_in_adv = 1;
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
pc_l3 = duk__get_current_pc(comp_ctx);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@ -5525,7 +5531,7 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
duk__advance(comp_ctx);
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */
duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
@ -5650,7 +5656,8 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
}
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
duk__advance(comp_ctx);
comp_ctx->curr_func.allow_regexp_in_adv = 1;
duk__advance(comp_ctx); /* Allow RegExp as part of next stmt. */
/* default case control flow patchup; note that if pc_prevcase < 0
* (i.e. no case clauses), control enters default case automatically.
@ -5702,7 +5709,8 @@ DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
DUK__SETTEMP(comp_ctx, temp_reset);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
comp_ctx->curr_func.allow_regexp_in_adv = 1;
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@ -5738,7 +5746,7 @@ DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d
DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
duk__advance(comp_ctx); /* eat 'do' */
duk__advance(comp_ctx); /* Eat 'do'; allow RegExp as part of next stmt. */
pc_start = duk__get_current_pc(comp_ctx);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@ -5752,6 +5760,7 @@ DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d
duk__emit_jump(comp_ctx, pc_start);
/* no need to reset temps, as we're finished emitting code */
comp_ctx->curr_func.allow_regexp_in_adv = 1; /* Allow RegExp as part of next stmt. */
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
@ -5781,7 +5790,8 @@ DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res
pc_jump_false = duk__emit_jump_empty(comp_ctx);
DUK__SETTEMP(comp_ctx, temp_reset);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
comp_ctx->curr_func.allow_regexp_in_adv = 1;
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
duk__emit_jump(comp_ctx, pc_start);
@ -6015,10 +6025,9 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
/* try part */
duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
duk__emit_op_only(comp_ctx,
DUK_OP_ENDTRY);
duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
/*
@ -6114,7 +6123,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
(duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
if (varmap_value == -2) {
@ -6156,7 +6165,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
duk__advance(comp_ctx);
duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
duk__emit_abc(comp_ctx,
DUK_OP_ENDFIN,
@ -6219,7 +6228,8 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
comp_ctx->curr_func.allow_regexp_in_adv = 1;
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
pc_trycatch = duk__get_current_pc(comp_ctx);
trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
@ -6231,8 +6241,7 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
duk__emit_invalid(comp_ctx); /* finished jump */
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
duk__emit_op_only(comp_ctx,
DUK_OP_ENDTRY);
duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
pc_finished = duk__get_current_pc(comp_ctx);
@ -6405,7 +6414,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
case DUK_TOK_LCURLY: {
DUK_DDD(DUK_DDDPRINT("block statement"));
duk__advance(comp_ctx);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
if (label_id >= 0) {
duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
@ -6784,7 +6793,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
* (EOF or closing brace).
*/
DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after) {
duk_hthread *thr = comp_ctx->thr;
duk_ivalue res_alloc;
duk_ivalue *res = &res_alloc;
@ -6832,6 +6841,15 @@ DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_sou
duk__parse_stmt(comp_ctx, res, allow_source_elem);
}
/* RegExp is allowed / not allowed depending on context. For function
* declarations RegExp is allowed because it follows a function
* declaration statement and may appear as part of the next statement.
* For function expressions RegExp is not allowed, and it's possible
* to do something like '(function () {} / 123)'.
*/
if (regexp_after) {
comp_ctx->curr_func.allow_regexp_in_adv = 1;
}
duk__advance(comp_ctx);
/* Tear down state. */
@ -7198,7 +7216,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
* token (EOF or closing brace).
*/
DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) {
DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token) {
duk_compiler_func *func;
duk_hthread *thr;
duk_regconst_t reg_stmt_value = -1;
@ -7270,7 +7288,9 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
func->max_line = 0;
#endif
/* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
* regexp literal" mode with current strictness.
*/
if (expect_token >= 0) {
/* Eating a left curly; regexp mode is allowed by left curly
* based on duk__token_lbp[] automatically.
@ -7289,7 +7309,8 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
duk__parse_stmts(comp_ctx,
1, /* allow source elements */
expect_eof); /* expect EOF instead of } */
expect_eof, /* expect EOF instead of } */
regexp_after); /* regexp after */
DUK_DDD(DUK_DDDPRINT("end 1st pass"));
/*
@ -7396,7 +7417,8 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
duk__parse_stmts(comp_ctx,
1, /* allow source elements */
expect_eof); /* expect EOF instead of } */
expect_eof, /* expect EOF instead of } */
regexp_after); /* regexp after */
DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
duk__update_lineinfo_currtoken(comp_ctx);
@ -7615,6 +7637,7 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui
duk__parse_func_body(comp_ctx,
0, /* expect_eof */
0, /* implicit_return_value */
flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
DUK_TOK_LCURLY); /* expect_token */
/*
@ -7667,6 +7690,14 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
duk__advance(comp_ctx);
/* RegExp is not allowed after a function expression, e.g. in
* (function () {} / 123). A RegExp *is* allowed after a
* function declaration!
*/
if (flags & DUK__FUNC_FLAG_DECL) {
comp_ctx->curr_func.allow_regexp_in_adv = 1;
}
duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
return fnum;
@ -7899,6 +7930,7 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
duk__parse_func_body(comp_ctx,
1, /* expect_eof */
1, /* implicit_return_value */
1, /* regexp_after (does not matter) */
-1); /* expect_token */
}

1
src-input/duk_js_compiler.h

@ -187,6 +187,7 @@ struct duk_compiler_func {
duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
duk_uint8_t needs_shuffle; /* function needs shuffle registers */
duk_uint8_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
duk_uint8_t allow_regexp_in_adv; /* allow RegExp literal on next advance() call */
};
struct duk_compiler_ctx {

Loading…
Cancel
Save