Skip to content

Commit d9121f4

Browse files
Fix parse of simple for statement.
Related issue: #156 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
1 parent 06136cf commit d9121f4

File tree

3 files changed

+240
-109
lines changed

3 files changed

+240
-109
lines changed

jerry-core/parser/js/parser.cpp

Lines changed: 182 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,67 @@ jsp_skip_braces (token_type brace_type) /**< type of the opening brace */
220220
current_token_must_be (closing_bracket_type);
221221
} /* jsp_skip_braces */
222222

223+
/**
224+
* Find next token of specified type before the specified location
225+
*
226+
* Note:
227+
* If skip_brace_blocks is true, every { should correspond to } brace before search end location,
228+
* otherwise a syntax error is raised.
229+
*
230+
* @return true - if token was found (in the case, it is the current token,
231+
* and lexer locus points to it),
232+
* false - otherwise (in the case, lexer locus points to end_loc).
233+
*/
234+
static bool
235+
jsp_find_next_token_before_the_locus (token_type token_to_find, /**< token to search for
236+
* (except TOK_NEWLINE and TOK_EOF) */
237+
locus end_loc, /**< location to search before */
238+
bool skip_brace_blocks) /**< skip blocks, surrounded with { and } braces */
239+
{
240+
JERRY_ASSERT (token_to_find != TOK_NEWLINE
241+
&& token_to_find != TOK_EOF);
242+
243+
while (tok.loc < end_loc)
244+
{
245+
if (skip_brace_blocks)
246+
{
247+
if (token_is (TOK_OPEN_BRACE))
248+
{
249+
jsp_skip_braces (TOK_OPEN_BRACE);
250+
251+
JERRY_ASSERT (token_is (TOK_CLOSE_BRACE));
252+
skip_newlines ();
253+
254+
if (tok.loc >= end_loc)
255+
{
256+
lexer_seek (end_loc);
257+
tok = lexer_next_token ();
258+
259+
return false;
260+
}
261+
}
262+
else if (token_is (TOK_CLOSE_BRACE))
263+
{
264+
EMIT_ERROR ("Unmatched } brace");
265+
}
266+
}
267+
268+
if (token_is (token_to_find))
269+
{
270+
return true;
271+
}
272+
else
273+
{
274+
JERRY_ASSERT (!token_is (TOK_EOF));
275+
}
276+
277+
skip_newlines ();
278+
}
279+
280+
JERRY_ASSERT (tok.loc == end_loc);
281+
return false;
282+
} /* jsp_find_next_token_before_the_locus */
283+
223284
/* property_name
224285
: Identifier
225286
| Keyword
@@ -1726,88 +1787,146 @@ parse_variable_declaration (void)
17261787
(LT!* ',' LT!* variable_declaration)*
17271788
; */
17281789
static void
1729-
parse_variable_declaration_list (bool *several_decls)
1790+
parse_variable_declaration_list (void)
17301791
{
1792+
JERRY_ASSERT (is_keyword (KW_VAR));
1793+
17311794
while (true)
17321795
{
1796+
skip_newlines ();
1797+
17331798
parse_variable_declaration ();
17341799

17351800
skip_newlines ();
17361801
if (!token_is (TOK_COMMA))
17371802
{
17381803
lexer_save_token (tok);
1739-
return;
1740-
}
1741-
1742-
skip_newlines ();
1743-
if (several_decls)
1744-
{
1745-
*several_decls = true;
1804+
break;
17461805
}
17471806
}
17481807
}
17491808

1809+
/**
1810+
* Parse for statement
1811+
*
1812+
* See also:
1813+
* ECMA-262 v5, 12.6.3
1814+
*
1815+
* Note:
1816+
* Syntax:
1817+
* Initializer Condition Increment Body LoopEnd
1818+
* - for ([ExpressionNoIn]; [Expression]; [Expression]) Statement
1819+
* - for (var VariableDeclarationListNoIn; [Expression]; [Expression]) Statement
1820+
*
1821+
* Note:
1822+
* Layout of generated byte-code is the following:
1823+
* Initializer ([ExpressionNoIn] / VariableDeclarationListNoIn)
1824+
* Jump -> ConditionCheck
1825+
* NextIteration:
1826+
* Body (Statement)
1827+
* ContinueTarget:
1828+
* Increment ([Expression])
1829+
* ConditionCheck:
1830+
* Condition ([Expression])
1831+
* If Condition is evaluted to true, jump -> NextIteration
1832+
*/
17501833
static void
1751-
parse_plain_for (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
1752-
* the statement (or NULL, if there are no named
1753-
* labels associated with the statement) */
1834+
jsp_parse_for_statement (jsp_label_t *outermost_stmt_label_p, /**< outermost (first) label, corresponding to
1835+
* the statement (or NULL, if there are no named
1836+
* labels associated with the statement) */
1837+
locus for_body_statement_loc) /**< locus of loop body statement */
17541838
{
1755-
dump_jump_to_end_for_rewrite ();
1756-
1757-
// Skip till body
1758-
JERRY_ASSERT (token_is (TOK_SEMICOLON));
1839+
current_token_must_be (TOK_OPEN_PAREN);
17591840
skip_newlines ();
1760-
const locus cond_loc = tok.loc;
1761-
while (!token_is (TOK_SEMICOLON))
1841+
1842+
// Initializer
1843+
if (is_keyword (KW_VAR))
17621844
{
1763-
skip_newlines ();
1845+
parse_variable_declaration_list ();
1846+
skip_token ();
17641847
}
1765-
skip_newlines ();
1766-
const locus incr_loc = tok.loc;
1767-
while (!token_is (TOK_CLOSE_PAREN))
1848+
else if (!token_is (TOK_SEMICOLON))
17681849
{
1769-
skip_newlines ();
1850+
parse_expression (false, JSP_EVAL_RET_STORE_NOT_DUMP);
1851+
skip_token ();
17701852
}
1853+
else
1854+
{
1855+
// Initializer is empty
1856+
}
1857+
1858+
// Jump -> ConditionCheck
1859+
dump_jump_to_end_for_rewrite ();
17711860

17721861
dumper_set_next_interation_target ();
17731862

1774-
// Parse body
1863+
current_token_must_be (TOK_SEMICOLON);
1864+
skip_token ();
1865+
1866+
// Save Condition locus
1867+
const locus condition_loc = tok.loc;
1868+
1869+
if (!jsp_find_next_token_before_the_locus (TOK_SEMICOLON,
1870+
for_body_statement_loc,
1871+
true))
1872+
{
1873+
EMIT_ERROR ("Invalid for statement");
1874+
}
1875+
1876+
current_token_must_be (TOK_SEMICOLON);
1877+
skip_token ();
1878+
1879+
// Save Increment locus
1880+
const locus increment_loc = tok.loc;
1881+
1882+
// Body
1883+
lexer_seek (for_body_statement_loc);
17751884
skip_newlines ();
1885+
17761886
parse_statement (NULL);
17771887

1778-
const locus end_loc = tok.loc;
1888+
// Save LoopEnd locus
1889+
const locus loop_end_loc = tok.loc;
17791890

1891+
// Setup ContinueTarget
17801892
jsp_label_setup_continue_target (outermost_stmt_label_p,
17811893
serializer_get_current_opcode_counter ());
17821894

1783-
lexer_seek (incr_loc);
1784-
skip_token ();
1895+
// Increment
1896+
lexer_seek (increment_loc);
1897+
skip_newlines ();
1898+
17851899
if (!token_is (TOK_CLOSE_PAREN))
17861900
{
17871901
parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
17881902
}
17891903

1904+
current_token_must_be (TOK_CLOSE_PAREN);
1905+
1906+
// Setup ConditionCheck
17901907
rewrite_jump_to_end ();
17911908

1792-
lexer_seek (cond_loc);
1793-
skip_token ();
1909+
// Condition
1910+
lexer_seek (condition_loc);
1911+
skip_newlines ();
1912+
17941913
if (token_is (TOK_SEMICOLON))
17951914
{
17961915
dump_continue_iterations_check (empty_operand ());
17971916
}
17981917
else
17991918
{
1800-
const operand cond = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
1919+
operand cond = parse_expression (true, JSP_EVAL_RET_STORE_NOT_DUMP);
18011920
dump_continue_iterations_check (cond);
18021921
}
18031922

1804-
lexer_seek (end_loc);
1805-
skip_token ();
1923+
lexer_seek (loop_end_loc);
1924+
skip_newlines ();
18061925
if (tok.type != TOK_CLOSE_BRACE)
18071926
{
18081927
lexer_save_token (tok);
18091928
}
1810-
}
1929+
} /* jsp_parse_for_statement */
18111930

18121931
static void
18131932
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,
18191938
EMIT_SORRY ("'for in' loops are not supported yet");
18201939
}
18211940

1822-
/* for_statement
1823-
: 'for' LT!* '(' (LT!* for_statement_initialiser_part)? LT!* ';'
1824-
(LT!* expression)? LT!* ';' (LT!* expression)? LT!* ')' LT!* statement
1825-
;
1826-
1827-
for_statement_initialiser_part
1828-
: expression
1829-
| 'var' LT!* variable_declaration_list
1830-
;
1831-
1832-
for_in_statement
1833-
: 'for' LT!* '(' LT!* for_in_statement_initialiser_part LT!* 'in'
1834-
LT!* expression LT!* ')' LT!* statement
1835-
;
1836-
1837-
for_in_statement_initialiser_part
1838-
: left_hand_side_expression
1839-
| 'var' LT!* variable_declaration
1840-
;*/
1841-
1941+
/**
1942+
* Parse for/for-in statements
1943+
*
1944+
* See also:
1945+
* ECMA-262 v5, 12.6.3 and 12.6.4
1946+
*/
18421947
static void
1843-
parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label, corresponding to
1844-
* the statement (or NULL, if there are no named
1845-
* labels associated with the statement) */
1948+
jsp_parse_for_or_for_in_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) label,
1949+
* corresponding to the statement
1950+
* (or NULL, if there are no name
1951+
* labels associated with the statement) */
18461952
{
18471953
assert_keyword (KW_FOR);
18481954
token_after_newlines_must_be (TOK_OPEN_PAREN);
18491955

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

1889-
/* expression contains left_hand_side_expression. */
1890-
parse_expression (false, JSP_EVAL_RET_STORE_NOT_DUMP);
1958+
for_open_paren_loc = tok.loc;
18911959

1960+
jsp_skip_braces (TOK_OPEN_PAREN);
18921961
skip_newlines ();
1893-
if (token_is (TOK_SEMICOLON))
1894-
{
1895-
parse_plain_for (outermost_stmt_label_p);
1896-
return;
1897-
}
1898-
else if (is_keyword (KW_IN))
1962+
1963+
for_body_statement_loc = tok.loc;
1964+
1965+
lexer_seek (for_open_paren_loc);
1966+
tok = lexer_next_token ();
1967+
1968+
bool is_plain_for = jsp_find_next_token_before_the_locus (TOK_SEMICOLON,
1969+
for_body_statement_loc,
1970+
true);
1971+
lexer_seek (for_open_paren_loc);
1972+
tok = lexer_next_token ();
1973+
1974+
if (is_plain_for)
18991975
{
1900-
parse_for_in (outermost_stmt_label_p);
1901-
return;
1976+
jsp_parse_for_statement (outermost_stmt_label_p, for_body_statement_loc);
19021977
}
19031978
else
19041979
{
1905-
EMIT_ERROR ("Expected either ';' or 'in' token");
1980+
parse_for_in (outermost_stmt_label_p);
19061981
}
1907-
}
1982+
} /* jsp_parse_for_or_for_in_statement */
19081983

19091984
static operand
19101985
parse_expression_inside_parens (void)
@@ -2318,7 +2393,7 @@ parse_iterational_statement (jsp_label_t *outermost_named_stmt_label_p) /**< out
23182393
else
23192394
{
23202395
JERRY_ASSERT (is_keyword (KW_FOR));
2321-
parse_for_or_for_in_statement (outermost_stmt_label_p);
2396+
jsp_parse_for_or_for_in_statement (outermost_stmt_label_p);
23222397
}
23232398

23242399
jsp_label_rewrite_jumps_and_pop (&label,
@@ -2412,8 +2487,7 @@ parse_statement (jsp_label_t *outermost_stmt_label_p) /**< outermost (first) lab
24122487
}
24132488
if (is_keyword (KW_VAR))
24142489
{
2415-
skip_newlines ();
2416-
parse_variable_declaration_list (NULL);
2490+
parse_variable_declaration_list ();
24172491
return;
24182492
}
24192493
if (is_keyword (KW_FUNCTION))

0 commit comments

Comments
 (0)