Skip to content

Commit 907eec1

Browse files
Fix parse of simple for statement.
Related issue: #156 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent 67c708f commit 907eec1

File tree

2 files changed

+171
-109
lines changed

2 files changed

+171
-109
lines changed

jerry-core/parser/js/parser.cpp

Lines changed: 154 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,39 @@ is_strict_mode (void)
171171
return scopes_tree_strict_mode (STACK_TOP (scopes));
172172
}
173173

174+
/**
175+
* Find next token of specified type before the specified location
176+
*
177+
* @return true - if token was found (in the case, it is the current token,
178+
* and lexer locus points to it),
179+
* false - otherwise (in the case, lexer locus points to end_loc).
180+
*/
181+
static bool
182+
jsp_find_next_token_before_the_locus (token_type token_to_find, /**< token to search for
183+
* (except TOK_NEWLINE and TOK_EOF) */
184+
locus end_loc) /**< location to search before */
185+
{
186+
JERRY_ASSERT (token_to_find != TOK_NEWLINE
187+
&& token_to_find != TOK_EOF);
188+
189+
while (tok.loc < end_loc)
190+
{
191+
if (token_is (token_to_find))
192+
{
193+
return true;
194+
}
195+
else
196+
{
197+
JERRY_ASSERT (!token_is (TOK_EOF));
198+
}
199+
200+
skip_newlines ();
201+
}
202+
203+
JERRY_ASSERT (tok.loc == end_loc);
204+
return false;
205+
} /* jsp_find_next_token_before_the_locus */
206+
174207
/**
175208
* Skip block, defined with braces of specified type
176209
*
@@ -1725,88 +1758,145 @@ parse_variable_declaration (void)
17251758
(LT!* ',' LT!* variable_declaration)*
17261759
; */
17271760
static void
1728-
parse_variable_declaration_list (bool *several_decls)
1761+
parse_variable_declaration_list (void)
17291762
{
1763+
JERRY_ASSERT (is_keyword (KW_VAR));
1764+
17301765
while (true)
17311766
{
1767+
skip_newlines ();
1768+
17321769
parse_variable_declaration ();
17331770

17341771
skip_newlines ();
17351772
if (!token_is (TOK_COMMA))
17361773
{
17371774
lexer_save_token (tok);
1738-
return;
1739-
}
1740-
1741-
skip_newlines ();
1742-
if (several_decls)
1743-
{
1744-
*several_decls = true;
1775+
break;
17451776
}
17461777
}
17471778
}
17481779

1780+
/**
1781+
* Parse for statement
1782+
*
1783+
* See also:
1784+
* ECMA-262 v5, 12.6.3
1785+
*
1786+
* Note:
1787+
* Syntax:
1788+
* Initializer Condition Increment Body LoopEnd
1789+
* - for ([ExpressionNoIn]; [Expression]; [Expression]) Statement
1790+
* - for (var VariableDeclarationListNoIn; [Expression]; [Expression]) Statement
1791+
*
1792+
* Note:
1793+
* Layout of generated byte-code is the following:
1794+
* Initializer ([ExpressionNoIn] / VariableDeclarationListNoIn)
1795+
* Jump -> ConditionCheck
1796+
* NextIteration:
1797+
* Body (Statement)
1798+
* ContinueTarget:
1799+
* Increment ([Expression])
1800+
* ConditionCheck:
1801+
* Condition ([Expression])
1802+
* If Condition is evaluted to true, jump -> NextIteration
1803+
*/
17491804
static void
1750-
parse_plain_for (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
1751-
* the statement (or NULL, if there are no named
1752-
* labels associated with the statement) */
1805+
jsp_parse_for_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost (first) label, corresponding to
1806+
* the statement (or NULL, if there are no named
1807+
* labels associated with the statement) */
1808+
locus for_body_statement_loc) /**< locus of loop body statement */
17531809
{
1754-
dump_jump_to_end_for_rewrite ();
1755-
1756-
// Skip till body
1757-
JERRY_ASSERT (token_is (TOK_SEMICOLON));
1810+
current_token_must_be (TOK_OPEN_PAREN);
17581811
skip_newlines ();
1759-
const locus cond_loc = tok.loc;
1760-
while (!token_is (TOK_SEMICOLON))
1812+
1813+
// Initializer
1814+
if (is_keyword (KW_VAR))
17611815
{
1762-
skip_newlines ();
1816+
parse_variable_declaration_list ();
1817+
skip_token ();
17631818
}
1764-
skip_newlines ();
1765-
const locus incr_loc = tok.loc;
1766-
while (!token_is (TOK_CLOSE_PAREN))
1819+
else if (!token_is (TOK_SEMICOLON))
17671820
{
1768-
skip_newlines ();
1821+
parse_expression (false, JSP_EVAL_RET_STORE_NOT_DUMP);
1822+
skip_token ();
1823+
}
1824+
else
1825+
{
1826+
// Initializer is empty
17691827
}
17701828

1829+
// Jump -> ConditionCheck
1830+
dump_jump_to_end_for_rewrite ();
1831+
17711832
dumper_set_next_interation_target ();
17721833

1773-
// Parse body
1774-
skip_newlines ();
1834+
current_token_must_be (TOK_SEMICOLON);
1835+
skip_token ();
1836+
1837+
// Save Condition locus
1838+
const locus condition_loc = tok.loc;
1839+
1840+
if (!jsp_find_next_token_before_the_locus (TOK_SEMICOLON,
1841+
for_body_statement_loc))
1842+
{
1843+
EMIT_ERROR ("Invalid for statement");
1844+
}
1845+
1846+
current_token_must_be (TOK_SEMICOLON);
1847+
skip_token ();
1848+
1849+
// Save Increment locus
1850+
const locus increment_loc = tok.loc;
1851+
1852+
// Body
1853+
lexer_seek (for_body_statement_loc);
1854+
tok = lexer_next_token ();
1855+
17751856
parse_statement (NULL);
17761857

1777-
const locus end_loc = tok.loc;
1858+
// Save LoopEnd locus
1859+
const locus loop_end_loc = tok.loc;
17781860

1861+
// Setup ContinueTarget
17791862
jsp_label_setup_continue_target (outermost_stmt_label_p,
17801863
serializer_get_current_opcode_counter ());
17811864

1782-
lexer_seek (incr_loc);
1783-
skip_token ();
1865+
// Increment
1866+
lexer_seek (increment_loc);
1867+
tok = lexer_next_token ();
1868+
17841869
if (!token_is (TOK_CLOSE_PAREN))
17851870
{
17861871
parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
17871872
}
17881873

1874+
current_token_must_be (TOK_CLOSE_PAREN);
1875+
1876+
// Setup ConditionCheck
17891877
rewrite_jump_to_end ();
17901878

1791-
lexer_seek (cond_loc);
1792-
skip_token ();
1879+
// Condition
1880+
lexer_seek (condition_loc);
1881+
tok = lexer_next_token ();
1882+
17931883
if (token_is (TOK_SEMICOLON))
17941884
{
17951885
dump_continue_iterations_check (empty_operand ());
17961886
}
17971887
else
17981888
{
1799-
const operand cond = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
1889+
operand cond = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
18001890
dump_continue_iterations_check (cond);
18011891
}
18021892

1803-
lexer_seek (end_loc);
1804-
skip_token ();
1893+
lexer_seek (loop_end_loc);
1894+
tok = lexer_next_token ();
18051895
if (tok.type != TOK_CLOSE_BRACE)
18061896
{
18071897
lexer_save_token (tok);
18081898
}
1809-
}
1899+
} /* jsp_parse_for_statement */
18101900

18111901
static void
18121902
parse_for_in (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
@@ -1818,92 +1908,48 @@ parse_for_in (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label,
18181908
EMIT_SORRY ("'for in' loops are not supported yet");
18191909
}
18201910

1821-
/* for_statement
1822-
: 'for' LT!* '(' (LT!* for_statement_initialiser_part)? LT!* ';'
1823-
(LT!* expression)? LT!* ';' (LT!* expression)? LT!* ')' LT!* statement
1824-
;
1825-
1826-
for_statement_initialiser_part
1827-
: expression
1828-
| 'var' LT!* variable_declaration_list
1829-
;
1830-
1831-
for_in_statement
1832-
: 'for' LT!* '(' LT!* for_in_statement_initialiser_part LT!* 'in'
1833-
LT!* expression LT!* ')' LT!* statement
1834-
;
1835-
1836-
for_in_statement_initialiser_part
1837-
: left_hand_side_expression
1838-
| 'var' LT!* variable_declaration
1839-
;*/
1840-
1911+
/**
1912+
* Parse for/for-in statements
1913+
*
1914+
* See also:
1915+
* ECMA-262 v5, 12.6.3 and 12.6.4
1916+
*/
18411917
static void
1842-
parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
1843-
* the statement (or NULL, if there are no named
1844-
* labels associated with the statement) */
1918+
jsp_parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label,
1919+
* corresponding to the statement
1920+
* (or NULL, if there are no name
1921+
* labels associated with the statement) */
18451922
{
18461923
assert_keyword (KW_FOR);
18471924
token_after_newlines_must_be (TOK_OPEN_PAREN);
18481925

1849-
skip_newlines ();
1850-
if (token_is (TOK_SEMICOLON))
1851-
{
1852-
parse_plain_for (outermost_stmt_label_p);
1853-
return;
1854-
}
1855-
/* Both for_statement_initialiser_part and for_in_statement_initialiser_part
1856-
contains 'var'. Check it first. */
1857-
if (is_keyword (KW_VAR))
1858-
{
1859-
bool several_decls = false;
1860-
skip_newlines ();
1861-
parse_variable_declaration_list (&several_decls);
1862-
if (several_decls)
1863-
{
1864-
token_after_newlines_must_be (TOK_SEMICOLON);
1865-
parse_plain_for (outermost_stmt_label_p);
1866-
return;
1867-
}
1868-
else
1869-
{
1870-
skip_newlines ();
1871-
if (token_is (TOK_SEMICOLON))
1872-
{
1873-
parse_plain_for (outermost_stmt_label_p);
1874-
return;
1875-
}
1876-
else if (is_keyword (KW_IN))
1877-
{
1878-
parse_for_in (outermost_stmt_label_p);
1879-
return;
1880-
}
1881-
else
1882-
{
1883-
EMIT_ERROR ("Expected either ';' or 'in' token");
1884-
}
1885-
}
1886-
}
1926+
locus for_open_paren_loc, for_body_statement_loc;
18871927

1888-
/* expression contains left_hand_side_expression. */
1889-
parse_expression (false, JSP_EVAL_RET_STORE_NOT_DUMP);
1928+
for_open_paren_loc = tok.loc;
18901929

1930+
jsp_skip_braces (TOK_OPEN_PAREN);
18911931
skip_newlines ();
1892-
if (token_is (TOK_SEMICOLON))
1893-
{
1894-
parse_plain_for (outermost_stmt_label_p);
1895-
return;
1896-
}
1897-
else if (is_keyword (KW_IN))
1932+
1933+
for_body_statement_loc = tok.loc;
1934+
1935+
lexer_seek (for_open_paren_loc);
1936+
tok = lexer_next_token ();
1937+
1938+
bool is_plain_for = jsp_find_next_token_before_the_locus (TOK_SEMICOLON,
1939+
for_body_statement_loc);
1940+
lexer_seek (for_open_paren_loc);
1941+
tok = lexer_next_token ();
1942+
1943+
if (is_plain_for)
18981944
{
1899-
parse_for_in (outermost_stmt_label_p);
1900-
return;
1945+
jsp_parse_for_statement (outermost_stmt_label_p, for_body_statement_loc);
19011946
}
19021947
else
19031948
{
1904-
EMIT_ERROR ("Expected either ';' or 'in' token");
1949+
parse_for_in (outermost_stmt_label_p);
19051950
}
1906-
}
1951+
1952+
} /* jsp_parse_for_or_for_in_statement */
19071953

19081954
static operand
19091955
parse_expression_inside_parens (void)
@@ -2317,7 +2363,7 @@ parse_iterational_statement (jsp_label_t *outermost_named_stmt_label_p) /**< out
23172363
else
23182364
{
23192365
JERRY_ASSERT (is_keyword (KW_FOR));
2320-
parse_for_or_for_in_statement (outermost_stmt_label_p);
2366+
jsp_parse_for_or_for_in_statement (outermost_stmt_label_p);
23212367
}
23222368

23232369
jsp_label_rewrite_jumps_and_pop (&label,
@@ -2411,8 +2457,7 @@ parse_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) lab
24112457
}
24122458
if (is_keyword (KW_VAR))
24132459
{
2414-
skip_newlines ();
2415-
parse_variable_declaration_list (NULL);
2460+
parse_variable_declaration_list ();
24162461
return;
24172462
}
24182463
if (is_keyword (KW_FUNCTION))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
function dec(x) { return x - 1 };
17+
for (var i = 0; i < 0; i = dec(i)) {}

0 commit comments

Comments
 (0)