From 3d5fd214f385661970b9611f62552ab1d95db5b2 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Sun, 5 Oct 2014 19:53:35 +0400 Subject: [PATCH] Add switch-case --- src/libjsparser/parser.c | 99 +++++++++++++++++++++++++++++++++++--- tests/jerry/switch_case.js | 43 +++++++++++++++++ 2 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 tests/jerry/switch_case.js diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 6a1f171ab..81f3e733e 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -1276,7 +1276,7 @@ parse_primary_expression (void) } default: { - JERRY_UNREACHABLE (); + EMIT_ERROR_VARG ("Unknown token %s", lexer_token_type_to_string (TOK ().type)); } } @@ -2483,6 +2483,11 @@ parse_statement_list (void) lexer_save_token (TOK ()); break; } + if (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT)) + { + lexer_save_token (TOK ()); + break; + } } STACK_CHECK_USAGE (IDX); @@ -2638,23 +2643,97 @@ parse_with_statement (void) STACK_CHECK_USAGE (IDX); } -/* case_block - : '{' LT!* case_clause* LT!* '}' - | '{' LT!* case_clause* LT!* default_clause LT!* case_clause* LT!* '}' - ; - case_clause +/* case_clause : 'case' LT!* expression LT!* ':' LT!* statement* ; default_clause : 'default' LT!* ':' LT!* statement* ; */ +static void +parse_case_clause (void) +{ + STACK_DECLARE_USAGE (IDX) + + assert_keyword (KW_CASE); + + skip_newlines (); + parse_expression (); + token_after_newlines_must_be (TOK_COLON); + + STACK_PUSH (IDX, next_temp_name ()); + DUMP_OPCODE_3 (equal_value_type, ID (1), ID (2), ID (3)); + STACK_PUSH (U16, OPCODE_COUNTER ()); + DUMP_OPCODE_3 (is_false_jmp_down, ID (1), INVALID_VALUE, INVALID_VALUE); + STACK_SWAP (IDX); + STACK_DROP (IDX, 1); + + skip_newlines (); + if (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT)) + { + lexer_save_token (TOK ()); + goto cleanup; + } + else + { + parse_statement_list (); + } + +cleanup: + STACK_CHECK_USAGE_LHS (); +} + /* switch_statement : 'switch' LT!* '(' LT!* expression LT!* ')' LT!* '{' LT!* case_block LT!* '}' - ; */ + ; + case_block + : '{' LT!* case_clause* LT!* '}' + | '{' LT!* case_clause* LT!* default_clause LT!* case_clause* LT!* '}' + ;*/ static void parse_switch_statement (void) { - EMIT_SORRY ("'switch' is not supported yet"); + STACK_DECLARE_USAGE (rewritable_break) + STACK_DECLARE_USAGE (IDX) + STACK_DECLARE_USAGE (U16) + + assert_keyword (KW_SWITCH); + + parse_expression_inside_parens (); + token_after_newlines_must_be (TOK_OPEN_BRACE); + push_nesting (NESTING_SWITCH); + skip_newlines (); + while (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT)) + { + if (is_keyword (KW_CASE)) + { + parse_case_clause (); + } + else if (is_keyword (KW_DEFAULT)) + { + EMIT_SORRY ("'default' clause is not supported yet"); + } + else + { + JERRY_UNREACHABLE (); + } + REWRITE_COND_JMP (STACK_TOP (U16), is_false_jmp_down, OPCODE_COUNTER () - STACK_TOP (U16)); + STACK_DROP (IDX, 1); + STACK_DROP (U16, 1); + skip_newlines (); + } + + if (!token_is (TOK_CLOSE_BRACE)) + { + EMIT_ERROR ("Expected '}' token"); + } + pop_nesting (NESTING_SWITCH); + STACK_DROP (IDX, 1); + + rewrite_rewritable_opcodes (REWRITABLE_BREAK, OPCODE_COUNTER ()); + + STACK_CHECK_USAGE (IDX); + STACK_CHECK_USAGE (U16); + STACK_CHECK_USAGE (rewritable_break); } /* catch_clause @@ -2882,6 +2961,10 @@ parse_statement (void) { goto cleanup; } + if (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT)) + { + goto cleanup; + } if (is_keyword (KW_IF)) { parse_if_statement (); diff --git a/tests/jerry/switch_case.js b/tests/jerry/switch_case.js new file mode 100644 index 000000000..0e024ba95 --- /dev/null +++ b/tests/jerry/switch_case.js @@ -0,0 +1,43 @@ +// Copyright 2014 Samsung Electronics Co., Ltd. +// +// 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. + +var a = 1; + +switch (a) { + case 1: + case 2: + break; + case 3: + assert (0); +} + +switch (a) { + case 1: + break; + case 2: + case 3: + assert (0); +} + +// TODO: Uncomment when default will be supported +/* +switch (a) { + default: + assert (0); + case 1: + break; + case 2: + case 3: + assert (0); +}*/