Fix: parsing regex and div operator correctly

JerryScript-DCO-1.0-Signed-off-by: Hanjoung Lee hanjoung.lee@samsung.com
This commit is contained in:
Hanjoung Lee 2015-10-08 16:47:35 +09:00
parent 86480f6168
commit 448984dd74
7 changed files with 137 additions and 23 deletions

View File

@ -1262,10 +1262,15 @@ lexer_parse_comment (void)
* Currently, lexer token doesn't fully correspond to Token, defined in ECMA-262, v5, 7.5.
* For example, there is no new-line token type in the token definition of ECMA-262 v5.
*
* Note:
* For Lexer alone, it is hard to find out a token is whether a regexp or a division.
* Parser must set maybe_regexp to true if a regexp is expected.
* Otherwise, a division is expected.
*
* @return constructed token
*/
static token
lexer_parse_token (void)
lexer_parse_token (bool maybe_regexp) /**< read '/' as regexp? */
{
ecma_char_t c = LA (0);
@ -1335,21 +1340,11 @@ lexer_parse_token (void)
}
else
{
return lexer_parse_token ();
return lexer_parse_token (maybe_regexp);
}
}
if (c == LIT_CHAR_SLASH
&& !(prev_non_lf_token.type == TOK_NAME
|| prev_non_lf_token.type == TOK_NULL
|| prev_non_lf_token.type == TOK_BOOL
|| prev_non_lf_token.type == TOK_CLOSE_BRACE
|| prev_non_lf_token.type == TOK_CLOSE_SQUARE
|| prev_non_lf_token.type == TOK_CLOSE_PAREN
|| prev_non_lf_token.type == TOK_SMALL_INT
|| prev_non_lf_token.type == TOK_NUMBER
|| prev_non_lf_token.type == TOK_STRING
|| prev_non_lf_token.type == TOK_REGEXP))
if (c == LIT_CHAR_SLASH && maybe_regexp)
{
return lexer_parse_regexp ();
}
@ -1517,7 +1512,7 @@ lexer_parse_token (void)
} /* lexer_parse_token */
token
lexer_next_token (void)
lexer_next_token (bool maybe_regexp) /**< read '/' as regexp? */
{
lit_utf8_iterator_pos_t src_pos = lit_utf8_iterator_get_pos (&src_iter);
if (src_pos.offset == 0 && !src_pos.is_non_bmp_middle)
@ -1546,7 +1541,7 @@ lexer_next_token (void)
}
prev_token = sent_token;
sent_token = lexer_parse_token ();
sent_token = lexer_parse_token (maybe_regexp);
if (sent_token.type == TOK_NEWLINE)
{

View File

@ -171,7 +171,7 @@ typedef struct
void lexer_init (const jerry_api_char_t *, size_t, bool);
token lexer_next_token (void);
token lexer_next_token (bool);
void lexer_save_token (token);
token lexer_prev_token (void);

View File

@ -95,9 +95,19 @@ token_data_as_lit_cp (void)
static void
skip_token (void)
{
tok = lexer_next_token ();
tok = lexer_next_token (false);
}
/**
* In case a regexp token is scanned as a division operator, rescan it
*/
static void
rescan_regexp_token (void)
{
lexer_seek (tok.loc);
tok = lexer_next_token (true);
} /* rescan_regexp_token */
static void
assert_keyword (keyword kw)
{
@ -252,7 +262,7 @@ jsp_find_next_token_before_the_locus (token_type token_to_find, /**< token to se
if (lit_utf8_iterator_pos_cmp (tok.loc, end_loc) >= 0)
{
lexer_seek (end_loc);
tok = lexer_next_token ();
tok = lexer_next_token (false);
return false;
}
@ -830,6 +840,13 @@ parse_primary_expression (void)
switch (tok.type)
{
case TOK_DIV:
case TOK_DIV_EQ:
{
// must be a regexp literal so rescan the token
rescan_regexp_token ();
/* FALLTHRU */
}
case TOK_NULL:
case TOK_BOOL:
case TOK_SMALL_INT:
@ -2129,7 +2146,7 @@ jsp_parse_for_in_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost
// Dump assignment VariableDeclarationNoIn / LeftHandSideExpression <- VM_REG_SPECIAL_FOR_IN_PROPERTY_NAME
lexer_seek (iterator_loc);
tok = lexer_next_token ();
tok = lexer_next_token (false);
jsp_operand_t iterator_base, iterator_identifier, for_in_special_reg;
for_in_special_reg = jsp_create_operand_for_in_special_reg ();
@ -2146,7 +2163,7 @@ jsp_parse_for_in_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost
// Body
lexer_seek (for_body_statement_loc);
tok = lexer_next_token ();
tok = lexer_next_token (false);
parse_statement (NULL);
@ -2164,7 +2181,7 @@ jsp_parse_for_in_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost
dump_for_in_end ();
lexer_seek (loop_end_loc);
tok = lexer_next_token ();
tok = lexer_next_token (false);
if (tok.type != TOK_CLOSE_BRACE)
{
lexer_save_token (tok);
@ -2201,13 +2218,13 @@ jsp_parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< out
for_body_statement_loc = tok.loc;
lexer_seek (for_open_paren_loc);
tok = lexer_next_token ();
tok = lexer_next_token (false);
bool is_plain_for = jsp_find_next_token_before_the_locus (TOK_SEMICOLON,
for_body_statement_loc,
true);
lexer_seek (for_open_paren_loc);
tok = lexer_next_token ();
tok = lexer_next_token (false);
if (is_plain_for)
{

View File

@ -65,3 +65,21 @@ try {
} catch (e) {
assert(e instanceof SyntaxError);
}
try {
eval("var x = /aaa/");
} catch (e) {
assert (false);
}
try {
eval("{}/a/g");
} catch (e) {
assert (false);
}
try {
eval("var a, g; +{}/a/g");
} catch (e) {
assert (false);
}

View File

@ -0,0 +1,32 @@
// Copyright 2015 Samsung Electronics Co., Ltd.
// Copyright 2015 University of Szeged.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
try {
eval('if (true) /abc/.exec("abc");');
} catch (e) {
assert (false);
}
try {
eval('if (true) {} /abc/.exec("abc");');
} catch (e) {
assert (false);
}
try {
eval('var a\n/abc/.exec("abc");');
} catch (e) {
assert (false);
}

View File

@ -0,0 +1,32 @@
// Copyright 2015 Samsung Electronics Co., Ltd.
// Copyright 2015 University of Szeged.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
try {
eval("this / 10");
} catch (e) {
assert (false);
}
try {
eval("var v_0 = 10;\nv_0++ / 1");
} catch (e) {
assert (false);
}
try {
eval("var v_0 = 10;\nif (v_0++ / 1) {\n}");
} catch (e) {
assert (false);
}

View File

@ -0,0 +1,20 @@
// Copyright 2015 Samsung Electronics Co., Ltd.
// Copyright 2015 University of Szeged.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
try {
eval("if (true) {}\n/a/;");
} catch (e) {
assert (false);
}