@@ -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 ; */
17281789static 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+ */
17501833static 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
18121931static void
18131932parse_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+ */
18421947static 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
19091984static operand
19101985parse_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