mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Fix parse of simple for statement.
Related issue: #156 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
parent
601f1eea58
commit
f849cc6283
@ -220,6 +220,67 @@ jsp_skip_braces (token_type brace_type) /**< type of the opening brace */
|
||||
current_token_must_be (closing_bracket_type);
|
||||
} /* jsp_skip_braces */
|
||||
|
||||
/**
|
||||
* Find next token of specified type before the specified location
|
||||
*
|
||||
* Note:
|
||||
* If skip_brace_blocks is true, every { should correspond to } brace before search end location,
|
||||
* otherwise a syntax error is raised.
|
||||
*
|
||||
* @return true - if token was found (in the case, it is the current token,
|
||||
* and lexer locus points to it),
|
||||
* false - otherwise (in the case, lexer locus points to end_loc).
|
||||
*/
|
||||
static bool
|
||||
jsp_find_next_token_before_the_locus (token_type token_to_find, /**< token to search for
|
||||
* (except TOK_NEWLINE and TOK_EOF) */
|
||||
locus end_loc, /**< location to search before */
|
||||
bool skip_brace_blocks) /**< skip blocks, surrounded with { and } braces */
|
||||
{
|
||||
JERRY_ASSERT (token_to_find != TOK_NEWLINE
|
||||
&& token_to_find != TOK_EOF);
|
||||
|
||||
while (tok.loc < end_loc)
|
||||
{
|
||||
if (skip_brace_blocks)
|
||||
{
|
||||
if (token_is (TOK_OPEN_BRACE))
|
||||
{
|
||||
jsp_skip_braces (TOK_OPEN_BRACE);
|
||||
|
||||
JERRY_ASSERT (token_is (TOK_CLOSE_BRACE));
|
||||
skip_newlines ();
|
||||
|
||||
if (tok.loc >= end_loc)
|
||||
{
|
||||
lexer_seek (end_loc);
|
||||
tok = lexer_next_token ();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (token_is (TOK_CLOSE_BRACE))
|
||||
{
|
||||
EMIT_ERROR ("Unmatched } brace");
|
||||
}
|
||||
}
|
||||
|
||||
if (token_is (token_to_find))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (!token_is (TOK_EOF));
|
||||
}
|
||||
|
||||
skip_newlines ();
|
||||
}
|
||||
|
||||
JERRY_ASSERT (tok.loc == end_loc);
|
||||
return false;
|
||||
} /* jsp_find_next_token_before_the_locus */
|
||||
|
||||
/* property_name
|
||||
: Identifier
|
||||
| Keyword
|
||||
@ -1726,88 +1787,146 @@ parse_variable_declaration (void)
|
||||
(LT!* ',' LT!* variable_declaration)*
|
||||
; */
|
||||
static void
|
||||
parse_variable_declaration_list (bool *several_decls)
|
||||
parse_variable_declaration_list (void)
|
||||
{
|
||||
JERRY_ASSERT (is_keyword (KW_VAR));
|
||||
|
||||
while (true)
|
||||
{
|
||||
skip_newlines ();
|
||||
|
||||
parse_variable_declaration ();
|
||||
|
||||
skip_newlines ();
|
||||
if (!token_is (TOK_COMMA))
|
||||
{
|
||||
lexer_save_token (tok);
|
||||
return;
|
||||
}
|
||||
|
||||
skip_newlines ();
|
||||
if (several_decls)
|
||||
{
|
||||
*several_decls = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse for statement
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 12.6.3
|
||||
*
|
||||
* Note:
|
||||
* Syntax:
|
||||
* Initializer Condition Increment Body LoopEnd
|
||||
* - for ([ExpressionNoIn]; [Expression]; [Expression]) Statement
|
||||
* - for (var VariableDeclarationListNoIn; [Expression]; [Expression]) Statement
|
||||
*
|
||||
* Note:
|
||||
* Layout of generated byte-code is the following:
|
||||
* Initializer ([ExpressionNoIn] / VariableDeclarationListNoIn)
|
||||
* Jump -> ConditionCheck
|
||||
* NextIteration:
|
||||
* Body (Statement)
|
||||
* ContinueTarget:
|
||||
* Increment ([Expression])
|
||||
* ConditionCheck:
|
||||
* Condition ([Expression])
|
||||
* If Condition is evaluted to true, jump -> NextIteration
|
||||
*/
|
||||
static void
|
||||
parse_plain_for (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
|
||||
* the statement (or NULL, if there are no named
|
||||
* labels associated with the statement) */
|
||||
jsp_parse_for_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost (first) label, corresponding to
|
||||
* the statement (or NULL, if there are no named
|
||||
* labels associated with the statement) */
|
||||
locus for_body_statement_loc) /**< locus of loop body statement */
|
||||
{
|
||||
dump_jump_to_end_for_rewrite ();
|
||||
current_token_must_be (TOK_OPEN_PAREN);
|
||||
skip_newlines ();
|
||||
|
||||
// Skip till body
|
||||
JERRY_ASSERT (token_is (TOK_SEMICOLON));
|
||||
skip_newlines ();
|
||||
const locus cond_loc = tok.loc;
|
||||
while (!token_is (TOK_SEMICOLON))
|
||||
// Initializer
|
||||
if (is_keyword (KW_VAR))
|
||||
{
|
||||
skip_newlines ();
|
||||
parse_variable_declaration_list ();
|
||||
skip_token ();
|
||||
}
|
||||
skip_newlines ();
|
||||
const locus incr_loc = tok.loc;
|
||||
while (!token_is (TOK_CLOSE_PAREN))
|
||||
else if (!token_is (TOK_SEMICOLON))
|
||||
{
|
||||
skip_newlines ();
|
||||
parse_expression (false, JSP_EVAL_RET_STORE_NOT_DUMP);
|
||||
skip_token ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initializer is empty
|
||||
}
|
||||
|
||||
// Jump -> ConditionCheck
|
||||
dump_jump_to_end_for_rewrite ();
|
||||
|
||||
dumper_set_next_interation_target ();
|
||||
|
||||
// Parse body
|
||||
current_token_must_be (TOK_SEMICOLON);
|
||||
skip_token ();
|
||||
|
||||
// Save Condition locus
|
||||
const locus condition_loc = tok.loc;
|
||||
|
||||
if (!jsp_find_next_token_before_the_locus (TOK_SEMICOLON,
|
||||
for_body_statement_loc,
|
||||
true))
|
||||
{
|
||||
EMIT_ERROR ("Invalid for statement");
|
||||
}
|
||||
|
||||
current_token_must_be (TOK_SEMICOLON);
|
||||
skip_token ();
|
||||
|
||||
// Save Increment locus
|
||||
const locus increment_loc = tok.loc;
|
||||
|
||||
// Body
|
||||
lexer_seek (for_body_statement_loc);
|
||||
skip_newlines ();
|
||||
|
||||
parse_statement (NULL);
|
||||
|
||||
const locus end_loc = tok.loc;
|
||||
// Save LoopEnd locus
|
||||
const locus loop_end_loc = tok.loc;
|
||||
|
||||
// Setup ContinueTarget
|
||||
jsp_label_setup_continue_target (outermost_stmt_label_p,
|
||||
serializer_get_current_opcode_counter ());
|
||||
|
||||
lexer_seek (incr_loc);
|
||||
skip_token ();
|
||||
// Increment
|
||||
lexer_seek (increment_loc);
|
||||
skip_newlines ();
|
||||
|
||||
if (!token_is (TOK_CLOSE_PAREN))
|
||||
{
|
||||
parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
|
||||
}
|
||||
|
||||
current_token_must_be (TOK_CLOSE_PAREN);
|
||||
|
||||
// Setup ConditionCheck
|
||||
rewrite_jump_to_end ();
|
||||
|
||||
lexer_seek (cond_loc);
|
||||
skip_token ();
|
||||
// Condition
|
||||
lexer_seek (condition_loc);
|
||||
skip_newlines ();
|
||||
|
||||
if (token_is (TOK_SEMICOLON))
|
||||
{
|
||||
dump_continue_iterations_check (empty_operand ());
|
||||
}
|
||||
else
|
||||
{
|
||||
const operand cond = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
|
||||
operand cond = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
|
||||
dump_continue_iterations_check (cond);
|
||||
}
|
||||
|
||||
lexer_seek (end_loc);
|
||||
skip_token ();
|
||||
lexer_seek (loop_end_loc);
|
||||
skip_newlines ();
|
||||
if (tok.type != TOK_CLOSE_BRACE)
|
||||
{
|
||||
lexer_save_token (tok);
|
||||
}
|
||||
}
|
||||
} /* jsp_parse_for_statement */
|
||||
|
||||
static void
|
||||
parse_for_in (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
|
||||
@ -1819,92 +1938,48 @@ parse_for_in (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label,
|
||||
EMIT_SORRY ("'for in' loops are not supported yet");
|
||||
}
|
||||
|
||||
/* for_statement
|
||||
: 'for' LT!* '(' (LT!* for_statement_initialiser_part)? LT!* ';'
|
||||
(LT!* expression)? LT!* ';' (LT!* expression)? LT!* ')' LT!* statement
|
||||
;
|
||||
|
||||
for_statement_initialiser_part
|
||||
: expression
|
||||
| 'var' LT!* variable_declaration_list
|
||||
;
|
||||
|
||||
for_in_statement
|
||||
: 'for' LT!* '(' LT!* for_in_statement_initialiser_part LT!* 'in'
|
||||
LT!* expression LT!* ')' LT!* statement
|
||||
;
|
||||
|
||||
for_in_statement_initialiser_part
|
||||
: left_hand_side_expression
|
||||
| 'var' LT!* variable_declaration
|
||||
;*/
|
||||
|
||||
/**
|
||||
* Parse for/for-in statements
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 12.6.3 and 12.6.4
|
||||
*/
|
||||
static void
|
||||
parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
|
||||
* the statement (or NULL, if there are no named
|
||||
* labels associated with the statement) */
|
||||
jsp_parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label,
|
||||
* corresponding to the statement
|
||||
* (or NULL, if there are no name
|
||||
* labels associated with the statement) */
|
||||
{
|
||||
assert_keyword (KW_FOR);
|
||||
token_after_newlines_must_be (TOK_OPEN_PAREN);
|
||||
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_SEMICOLON))
|
||||
{
|
||||
parse_plain_for (outermost_stmt_label_p);
|
||||
return;
|
||||
}
|
||||
/* Both for_statement_initialiser_part and for_in_statement_initialiser_part
|
||||
contains 'var'. Check it first. */
|
||||
if (is_keyword (KW_VAR))
|
||||
{
|
||||
bool several_decls = false;
|
||||
skip_newlines ();
|
||||
parse_variable_declaration_list (&several_decls);
|
||||
if (several_decls)
|
||||
{
|
||||
token_after_newlines_must_be (TOK_SEMICOLON);
|
||||
parse_plain_for (outermost_stmt_label_p);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_SEMICOLON))
|
||||
{
|
||||
parse_plain_for (outermost_stmt_label_p);
|
||||
return;
|
||||
}
|
||||
else if (is_keyword (KW_IN))
|
||||
{
|
||||
parse_for_in (outermost_stmt_label_p);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_ERROR ("Expected either ';' or 'in' token");
|
||||
}
|
||||
}
|
||||
}
|
||||
locus for_open_paren_loc, for_body_statement_loc;
|
||||
|
||||
/* expression contains left_hand_side_expression. */
|
||||
parse_expression (false, JSP_EVAL_RET_STORE_NOT_DUMP);
|
||||
for_open_paren_loc = tok.loc;
|
||||
|
||||
jsp_skip_braces (TOK_OPEN_PAREN);
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_SEMICOLON))
|
||||
|
||||
for_body_statement_loc = tok.loc;
|
||||
|
||||
lexer_seek (for_open_paren_loc);
|
||||
tok = lexer_next_token ();
|
||||
|
||||
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 ();
|
||||
|
||||
if (is_plain_for)
|
||||
{
|
||||
parse_plain_for (outermost_stmt_label_p);
|
||||
return;
|
||||
}
|
||||
else if (is_keyword (KW_IN))
|
||||
{
|
||||
parse_for_in (outermost_stmt_label_p);
|
||||
return;
|
||||
jsp_parse_for_statement (outermost_stmt_label_p, for_body_statement_loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_ERROR ("Expected either ';' or 'in' token");
|
||||
parse_for_in (outermost_stmt_label_p);
|
||||
}
|
||||
}
|
||||
} /* jsp_parse_for_or_for_in_statement */
|
||||
|
||||
static operand
|
||||
parse_expression_inside_parens (void)
|
||||
@ -2318,7 +2393,7 @@ parse_iterational_statement (jsp_label_t *outermost_named_stmt_label_p) /**< out
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (is_keyword (KW_FOR));
|
||||
parse_for_or_for_in_statement (outermost_stmt_label_p);
|
||||
jsp_parse_for_or_for_in_statement (outermost_stmt_label_p);
|
||||
}
|
||||
|
||||
jsp_label_rewrite_jumps_and_pop (&label,
|
||||
@ -2412,8 +2487,7 @@ parse_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) lab
|
||||
}
|
||||
if (is_keyword (KW_VAR))
|
||||
{
|
||||
skip_newlines ();
|
||||
parse_variable_declaration_list (NULL);
|
||||
parse_variable_declaration_list ();
|
||||
return;
|
||||
}
|
||||
if (is_keyword (KW_FUNCTION))
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
// Copyright 2014-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.
|
||||
@ -12,15 +13,18 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// 1.
|
||||
var i = 0;
|
||||
for (; i < 100; i++) {
|
||||
}
|
||||
assert(i == 100);
|
||||
|
||||
// 2.
|
||||
for (var j = 0; j < 100; j++) {
|
||||
}
|
||||
assert(j == 100);
|
||||
|
||||
// 3.
|
||||
for (i = 0; ; ) {
|
||||
if (i == 100) {
|
||||
break;
|
||||
@ -30,6 +34,7 @@ for (i = 0; ; ) {
|
||||
}
|
||||
assert(i == 100);
|
||||
|
||||
// 4.
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 0; j < 10; j++) {
|
||||
}
|
||||
@ -38,3 +43,36 @@ assert(i != 100);
|
||||
assert(j != 100);
|
||||
assert(i == 10);
|
||||
assert(j == 10);
|
||||
|
||||
// 5.
|
||||
s = '';
|
||||
for (
|
||||
var i = {x: 0};
|
||||
|
||||
i.x < 2
|
||||
;
|
||||
i.x++
|
||||
|
||||
)
|
||||
{
|
||||
s += i.x;
|
||||
}
|
||||
|
||||
assert (s === '01');
|
||||
|
||||
// 6.
|
||||
s = '';
|
||||
for (
|
||||
var i = {x: 0};
|
||||
|
||||
i.x < 2
|
||||
;
|
||||
|
||||
i.x++
|
||||
|
||||
)
|
||||
{
|
||||
s += i.x;
|
||||
}
|
||||
|
||||
assert (s === '01');
|
||||
|
||||
19
tests/jerry/regression-test-issue-156.js
Normal file
19
tests/jerry/regression-test-issue-156.js
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
function dec(x) { return x - 1 };
|
||||
for (var i = 5; i > 0; i = dec(i)) {}
|
||||
for (var i = 11; i = dec (i); i--) {}
|
||||
for (var i = dec (12); i > 0; i--) {}
|
||||
Loading…
x
Reference in New Issue
Block a user