diff --git a/jerry-core/parser/js/common.h b/jerry-core/parser/js/common.h index 16ad5062e5..1847977222 100644 --- a/jerry-core/parser/js/common.h +++ b/jerry-core/parser/js/common.h @@ -47,6 +47,7 @@ */ typedef enum { + /* The LEXER_IS_IDENT_OR_STRING macro must be updated if the order is changed. */ LEXER_IDENT_LITERAL = 0, /**< identifier literal */ LEXER_STRING_LITERAL = 1, /**< string literal */ LEXER_NUMBER_LITERAL = 2, /**< number literal */ @@ -56,6 +57,11 @@ typedef enum used by the byte code generator. */ } lexer_literal_type_t; +/** + * Checks whether the literal type is identifier or string. + */ +#define LEXER_IS_IDENT_OR_STRING(literal_type) ((literal_type) <= LEXER_STRING_LITERAL) + /** * Flag bits for status_flags member of lexer_literal_t. */ diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index 64aaae1a99..f7b1c68c8a 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -2331,12 +2331,12 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ if (context_p->source_p < context_p->source_end_p && context_p->source_p[0] != LIT_CHAR_COLON) { - if (lexer_compare_raw_identifier_to_current (context_p, "get", 3)) + if (lexer_compare_literal_to_string (context_p, "get", 3)) { context_p->token.type = LEXER_PROPERTY_GETTER; return; } - else if (lexer_compare_raw_identifier_to_current (context_p, "set", 3)) + else if (lexer_compare_literal_to_string (context_p, "set", 3)) { context_p->token.type = LEXER_PROPERTY_SETTER; return; @@ -2345,8 +2345,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ } #if ENABLED (JERRY_ES2015_CLASS) - if (is_class_method - && lexer_compare_raw_identifier_to_current (context_p, "static", 6)) + if (is_class_method && lexer_compare_literal_to_string (context_p, "static", 6)) { context_p->token.type = LEXER_KEYW_STATIC; return; @@ -2406,8 +2405,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ if (create_literal_object) { #if ENABLED (JERRY_ES2015_CLASS) - if (is_class_method - && lexer_compare_raw_identifier_to_current (context_p, "constructor", 11)) + if (is_class_method && lexer_compare_literal_to_string (context_p, "constructor", 11)) { context_p->token.type = LEXER_CLASS_CONSTRUCTOR; return; @@ -2447,11 +2445,11 @@ lexer_scan_identifier (parser_context_t *context_p, /**< context */ if (context_p->source_p < context_p->source_end_p && context_p->source_p[0] != LIT_CHAR_COLON) { - if (lexer_compare_raw_identifier_to_current (context_p, "get", 3)) + if (lexer_compare_literal_to_string (context_p, "get", 3)) { context_p->token.type = LEXER_PROPERTY_GETTER; } - else if (lexer_compare_raw_identifier_to_current (context_p, "set", 3)) + else if (lexer_compare_literal_to_string (context_p, "set", 3)) { context_p->token.type = LEXER_PROPERTY_SETTER; } @@ -2573,27 +2571,46 @@ lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context * } /* lexer_compare_identifier_to_current */ /** - * Compares the current identifier in the context to the parameter identifier + * Compares the current identifier to an expected identifier. * * Note: * Escape sequences are not allowed. * - * @return true if the input identifiers are the same + * @return true if they are the same, false otherwise */ -bool -lexer_compare_raw_identifier_to_current (parser_context_t *context_p, /**< context */ - const char *right_ident_p, /**< identifier */ - size_t right_ident_length) /**< identifier length */ +inline bool JERRY_ATTR_ALWAYS_INLINE +lexer_compare_literal_to_identifier (parser_context_t *context_p, /**< context */ + const char *identifier_p, /**< identifier */ + size_t identifier_length) /**< identifier length */ { - lexer_lit_location_t *left_ident_p = &context_p->token.lit_location; - - if (left_ident_p->length != right_ident_length || left_ident_p->has_escape) - { - return 0; - } + /* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */ + return (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL + && context_p->token.lit_location.length == identifier_length + && memcmp (context_p->token.lit_location.char_p, identifier_p, identifier_length) == 0); +} /* lexer_compare_literal_to_identifier */ - return memcmp (left_ident_p->char_p, right_ident_p, right_ident_length) == 0; -} /* lexer_compare_raw_identifier_to_current */ +/** + * Compares the current identifier or string to an expected string. + * + * Note: + * Escape sequences are not allowed. + * + * @return true if they are the same, false otherwise + */ +inline bool JERRY_ATTR_ALWAYS_INLINE +lexer_compare_literal_to_string (parser_context_t *context_p, /**< context */ + const char *string_p, /**< string */ + size_t string_length) /**< string length */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL)); + + /* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */ + return (context_p->token.lit_location.length == string_length + && memcmp (context_p->token.lit_location.char_p, string_p, string_length) == 0); +} /* lexer_compare_literal_to_string */ /** * Convert binary lvalue token to binary token diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 2ef267a084..2f2d71988b 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -435,7 +435,8 @@ parser_parse_class_literal (parser_context_t *context_p) /**< context */ is_computed = true; } else if (!(status_flags & PARSER_CLASS_STATIC_FUNCTION) - && lexer_compare_raw_identifier_to_current (context_p, "constructor", 11)) + && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_literal_to_string (context_p, "constructor", 11)) { parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR); } @@ -531,7 +532,8 @@ parser_parse_class_literal (parser_context_t *context_p) /**< context */ is_computed = true; } else if ((status_flags & PARSER_CLASS_STATIC_FUNCTION) - && lexer_compare_raw_identifier_to_current (context_p, "prototype", 9)) + && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_literal_to_string (context_p, "prototype", 9)) { parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE); } diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 6a28225d27..1fd81e11f2 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -521,8 +521,9 @@ void lexer_convert_push_number_to_push_literal (parser_context_t *context_p); uint16_t lexer_construct_function_object (parser_context_t *context_p, uint32_t extra_status_flags); void lexer_construct_regexp_object (parser_context_t *context_p, bool parse_only); bool lexer_compare_identifier_to_current (parser_context_t *context_p, const lexer_lit_location_t *right_ident_p); -bool lexer_compare_raw_identifier_to_current (parser_context_t *context_p, const char *right_ident_p, - size_t right_ident_length); +bool lexer_compare_literal_to_identifier (parser_context_t *context_p, const char *identifier_p, + size_t identifier_length); +bool lexer_compare_literal_to_string (parser_context_t *context_p, const char *string_p, size_t string_length); uint8_t lexer_convert_binary_lvalue_token_to_binary (uint8_t token); /** diff --git a/jerry-core/parser/js/js-parser-module.c b/jerry-core/parser/js/js-parser-module.c index a616ee63fb..77d4f629d5 100644 --- a/jerry-core/parser/js/js-parser-module.c +++ b/jerry-core/parser/js/js-parser-module.c @@ -362,8 +362,7 @@ parser_module_parse_export_clause (parser_context_t *context_p) /**< parser cont uint16_t export_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; lexer_next_token (context_p); - if (context_p->token.type == LEXER_LITERAL - && lexer_compare_raw_identifier_to_current (context_p, "as", 2)) + if (lexer_compare_literal_to_identifier (context_p, "as", 2)) { lexer_next_token (context_p); @@ -415,8 +414,7 @@ parser_module_parse_export_clause (parser_context_t *context_p) /**< parser cont lexer_next_token (context_p); } - if (context_p->token.type == LEXER_LITERAL - && lexer_compare_raw_identifier_to_current (context_p, "from", 4)) + if (lexer_compare_literal_to_identifier (context_p, "from", 4)) { parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); } @@ -455,8 +453,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; lexer_next_token (context_p); - if (context_p->token.type == LEXER_LITERAL - && lexer_compare_raw_identifier_to_current (context_p, "as", 2)) + if (lexer_compare_literal_to_identifier (context_p, "as", 2)) { lexer_next_token (context_p); @@ -508,8 +505,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont lexer_next_token (context_p); } - if (context_p->token.type == LEXER_LITERAL - && lexer_compare_raw_identifier_to_current (context_p, "from", 4)) + if (lexer_compare_literal_to_identifier (context_p, "from", 4)) { parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); } diff --git a/jerry-core/parser/js/js-parser-scanner.c b/jerry-core/parser/js/js-parser-scanner.c index 2673588fa0..fe36c11f9d 100644 --- a/jerry-core/parser/js/js-parser-scanner.c +++ b/jerry-core/parser/js/js-parser-scanner.c @@ -720,7 +720,7 @@ parser_scan_until (parser_context_t *context_p, /**< context */ context_p->token.type = LEXER_KEYW_IN; return; } - else if (type == LEXER_LITERAL && lexer_compare_raw_identifier_to_current (context_p, "of", 2)) + else if (lexer_compare_literal_to_identifier (context_p, "of", 2)) { parser_stack_pop_uint8 (context_p); context_p->token.type = LEXER_LITERAL_OF; @@ -788,13 +788,13 @@ parser_scan_until (parser_context_t *context_p, /**< context */ break; } - if (lexer_compare_raw_identifier_to_current (context_p, "static", 6)) + if (lexer_compare_literal_to_identifier (context_p, "static", 6)) { lexer_next_token (context_p); } - if (lexer_compare_raw_identifier_to_current (context_p, "get", 3) - || lexer_compare_raw_identifier_to_current (context_p, "set", 3)) + if (lexer_compare_literal_to_identifier (context_p, "get", 3) + || lexer_compare_literal_to_identifier (context_p, "set", 3)) { lexer_next_token (context_p); } diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c index 0f59207278..4547a8ac65 100644 --- a/jerry-core/parser/js/js-parser-statm.c +++ b/jerry-core/parser/js/js-parser-statm.c @@ -1884,12 +1884,6 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context lexer_next_token (context_p); - if (context_p->token.type != LEXER_COMMA - && !lexer_compare_raw_identifier_to_current (context_p, "from", 4)) - { - parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED); - } - if (context_p->token.type == LEXER_COMMA) { lexer_next_token (context_p); @@ -1899,14 +1893,17 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED); } } + else if (!lexer_compare_literal_to_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED); + } } if (context_p->token.type == LEXER_MULTIPLY) { /* NameSpaceImport*/ lexer_next_token (context_p); - if (context_p->token.type != LEXER_LITERAL - || !lexer_compare_raw_identifier_to_current (context_p, "as", 2)) + if (!lexer_compare_literal_to_identifier (context_p, "as", 2)) { parser_raise_error (context_p, PARSER_ERR_AS_EXPECTED); } @@ -1942,7 +1939,7 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context parser_module_parse_import_clause (context_p); } - if (context_p->token.type != LEXER_LITERAL || !lexer_compare_raw_identifier_to_current (context_p, "from", 4)) + if (!lexer_compare_literal_to_identifier (context_p, "from", 4)) { parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED); } @@ -2035,8 +2032,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */ case LEXER_MULTIPLY: { lexer_next_token (context_p); - if (!(context_p->token.type == LEXER_LITERAL - && lexer_compare_raw_identifier_to_current (context_p, "from", 4))) + if (!lexer_compare_literal_to_identifier (context_p, "from", 4)) { parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED); } @@ -2106,8 +2102,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */ { parser_module_parse_export_clause (context_p); - if (context_p->token.type == LEXER_LITERAL - && lexer_compare_raw_identifier_to_current (context_p, "from", 4)) + if (lexer_compare_literal_to_identifier (context_p, "from", 4)) { lexer_next_token (context_p); parser_module_handle_module_specifier (context_p); diff --git a/tests/jerry/es2015/for-of.js b/tests/jerry/es2015/for-of.js index f76ff1b406..3ba8f0e7c5 100644 --- a/tests/jerry/es2015/for-of.js +++ b/tests/jerry/es2015/for-of.js @@ -52,6 +52,10 @@ var forOf = " obj[prop] += 4;" parse (forOf) +var forOf = + "for (var a \"of\" []) {}" +parse (forOf) + checkError(5) var obj = {}