1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "js-parser-internal.h" 17425bb815Sopenharmony_ci#include "js-scanner-internal.h" 18425bb815Sopenharmony_ci#include "lit-char-helpers.h" 19425bb815Sopenharmony_ci 20425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER) 21425bb815Sopenharmony_ci 22425bb815Sopenharmony_ci/** \addtogroup parser Parser 23425bb815Sopenharmony_ci * @{ 24425bb815Sopenharmony_ci * 25425bb815Sopenharmony_ci * \addtogroup jsparser JavaScript 26425bb815Sopenharmony_ci * @{ 27425bb815Sopenharmony_ci * 28425bb815Sopenharmony_ci * \addtogroup jsparser_scanner Scanner 29425bb815Sopenharmony_ci * @{ 30425bb815Sopenharmony_ci */ 31425bb815Sopenharmony_ci 32425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 33425bb815Sopenharmony_ci 34425bb815Sopenharmony_ci/** 35425bb815Sopenharmony_ci * Add the "async" literal to the literal pool. 36425bb815Sopenharmony_ci */ 37425bb815Sopenharmony_civoid 38425bb815Sopenharmony_ciscanner_add_async_literal (parser_context_t *context_p, /**< context */ 39425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 40425bb815Sopenharmony_ci{ 41425bb815Sopenharmony_ci lexer_lit_location_t async_literal; 42425bb815Sopenharmony_ci 43425bb815Sopenharmony_ci JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC); 44425bb815Sopenharmony_ci 45425bb815Sopenharmony_ci parser_stack_pop_uint8 (context_p); 46425bb815Sopenharmony_ci parser_stack_pop (context_p, &async_literal, sizeof (lexer_lit_location_t)); 47425bb815Sopenharmony_ci 48425bb815Sopenharmony_ci lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p, 49425bb815Sopenharmony_ci scanner_context_p->active_literal_pool_p, 50425bb815Sopenharmony_ci &async_literal); 51425bb815Sopenharmony_ci 52425bb815Sopenharmony_ci lit_location_p->type |= SCANNER_LITERAL_IS_USED; 53425bb815Sopenharmony_ci 54425bb815Sopenharmony_ci if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) 55425bb815Sopenharmony_ci { 56425bb815Sopenharmony_ci lit_location_p->type |= SCANNER_LITERAL_NO_REG; 57425bb815Sopenharmony_ci } 58425bb815Sopenharmony_ci} /* scanner_add_async_literal */ 59425bb815Sopenharmony_ci 60425bb815Sopenharmony_ci/** 61425bb815Sopenharmony_ci * Init scanning the body of an arrow function. 62425bb815Sopenharmony_ci */ 63425bb815Sopenharmony_cistatic void 64425bb815Sopenharmony_ciscanner_check_arrow_body (parser_context_t *context_p, /**< context */ 65425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 66425bb815Sopenharmony_ci{ 67425bb815Sopenharmony_ci lexer_next_token (context_p); 68425bb815Sopenharmony_ci 69425bb815Sopenharmony_ci if (context_p->token.type != LEXER_LEFT_BRACE) 70425bb815Sopenharmony_ci { 71425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; 72425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_EXPRESSION); 73425bb815Sopenharmony_ci return; 74425bb815Sopenharmony_ci } 75425bb815Sopenharmony_ci 76425bb815Sopenharmony_ci lexer_next_token (context_p); 77425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_ARROW); 78425bb815Sopenharmony_ci scanner_check_directives (context_p, scanner_context_p); 79425bb815Sopenharmony_ci} /* scanner_check_arrow_body */ 80425bb815Sopenharmony_ci 81425bb815Sopenharmony_ci/** 82425bb815Sopenharmony_ci * Process arrow function with argument list. 83425bb815Sopenharmony_ci */ 84425bb815Sopenharmony_civoid 85425bb815Sopenharmony_ciscanner_check_arrow (parser_context_t *context_p, /**< context */ 86425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 87425bb815Sopenharmony_ci{ 88425bb815Sopenharmony_ci parser_stack_pop_uint8 (context_p); 89425bb815Sopenharmony_ci 90425bb815Sopenharmony_ci lexer_next_token (context_p); 91425bb815Sopenharmony_ci 92425bb815Sopenharmony_ci if (context_p->token.type != LEXER_ARROW 93425bb815Sopenharmony_ci || (context_p->token.flags & LEXER_WAS_NEWLINE)) 94425bb815Sopenharmony_ci { 95425bb815Sopenharmony_ci if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) 96425bb815Sopenharmony_ci { 97425bb815Sopenharmony_ci scanner_add_async_literal (context_p, scanner_context_p); 98425bb815Sopenharmony_ci } 99425bb815Sopenharmony_ci 100425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; 101425bb815Sopenharmony_ci scanner_pop_literal_pool (context_p, scanner_context_p); 102425bb815Sopenharmony_ci return; 103425bb815Sopenharmony_ci } 104425bb815Sopenharmony_ci 105425bb815Sopenharmony_ci if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) 106425bb815Sopenharmony_ci { 107425bb815Sopenharmony_ci parser_stack_pop (context_p, NULL, sizeof (lexer_lit_location_t) + 1); 108425bb815Sopenharmony_ci } 109425bb815Sopenharmony_ci 110425bb815Sopenharmony_ci scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; 111425bb815Sopenharmony_ci uint16_t status_flags = literal_pool_p->status_flags; 112425bb815Sopenharmony_ci 113425bb815Sopenharmony_ci status_flags |= SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS; 114425bb815Sopenharmony_ci status_flags &= (uint16_t) ~(SCANNER_LITERAL_POOL_IN_WITH 115425bb815Sopenharmony_ci | SCANNER_LITERAL_POOL_GENERATOR 116425bb815Sopenharmony_ci | SCANNER_LITERAL_POOL_ASYNC); 117425bb815Sopenharmony_ci 118425bb815Sopenharmony_ci context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); 119425bb815Sopenharmony_ci 120425bb815Sopenharmony_ci if (status_flags & SCANNER_LITERAL_POOL_ASYNC_ARROW) 121425bb815Sopenharmony_ci { 122425bb815Sopenharmony_ci status_flags |= SCANNER_LITERAL_POOL_ASYNC; 123425bb815Sopenharmony_ci context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; 124425bb815Sopenharmony_ci } 125425bb815Sopenharmony_ci 126425bb815Sopenharmony_ci literal_pool_p->status_flags = status_flags; 127425bb815Sopenharmony_ci 128425bb815Sopenharmony_ci scanner_filter_arguments (context_p, scanner_context_p); 129425bb815Sopenharmony_ci scanner_check_arrow_body (context_p, scanner_context_p); 130425bb815Sopenharmony_ci} /* scanner_check_arrow */ 131425bb815Sopenharmony_ci 132425bb815Sopenharmony_ci/** 133425bb815Sopenharmony_ci * Process arrow function with a single argument. 134425bb815Sopenharmony_ci */ 135425bb815Sopenharmony_civoid 136425bb815Sopenharmony_ciscanner_scan_simple_arrow (parser_context_t *context_p, /**< context */ 137425bb815Sopenharmony_ci scanner_context_t *scanner_context_p, /**< scanner context */ 138425bb815Sopenharmony_ci const uint8_t *source_p) /**< identifier end position */ 139425bb815Sopenharmony_ci{ 140425bb815Sopenharmony_ci uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS; 141425bb815Sopenharmony_ci 142425bb815Sopenharmony_ci context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); 143425bb815Sopenharmony_ci 144425bb815Sopenharmony_ci if (scanner_context_p->async_source_p != NULL) 145425bb815Sopenharmony_ci { 146425bb815Sopenharmony_ci JERRY_ASSERT (scanner_context_p->async_source_p == source_p); 147425bb815Sopenharmony_ci 148425bb815Sopenharmony_ci status_flags |= SCANNER_LITERAL_POOL_ASYNC; 149425bb815Sopenharmony_ci context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; 150425bb815Sopenharmony_ci } 151425bb815Sopenharmony_ci 152425bb815Sopenharmony_ci scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags); 153425bb815Sopenharmony_ci literal_pool_p->source_p = source_p; 154425bb815Sopenharmony_ci 155425bb815Sopenharmony_ci lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p); 156425bb815Sopenharmony_ci location_p->type |= SCANNER_LITERAL_IS_ARG; 157425bb815Sopenharmony_ci 158425bb815Sopenharmony_ci /* Skip the => token, which size is two. */ 159425bb815Sopenharmony_ci context_p->source_p += 2; 160425bb815Sopenharmony_ci PARSER_PLUS_EQUAL_LC (context_p->column, 2); 161425bb815Sopenharmony_ci context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES); 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_ci scanner_check_arrow_body (context_p, scanner_context_p); 164425bb815Sopenharmony_ci} /* scanner_scan_simple_arrow */ 165425bb815Sopenharmony_ci 166425bb815Sopenharmony_ci/** 167425bb815Sopenharmony_ci * Process the next argument of a might-be arrow function. 168425bb815Sopenharmony_ci */ 169425bb815Sopenharmony_civoid 170425bb815Sopenharmony_ciscanner_check_arrow_arg (parser_context_t *context_p, /**< context */ 171425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 172425bb815Sopenharmony_ci{ 173425bb815Sopenharmony_ci JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); 174425bb815Sopenharmony_ci 175425bb815Sopenharmony_ci const uint8_t *source_p = context_p->source_p; 176425bb815Sopenharmony_ci bool process_arrow = false; 177425bb815Sopenharmony_ci 178425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; 179425bb815Sopenharmony_ci 180425bb815Sopenharmony_ci if (context_p->token.type == LEXER_THREE_DOTS) 181425bb815Sopenharmony_ci { 182425bb815Sopenharmony_ci lexer_next_token (context_p); 183425bb815Sopenharmony_ci } 184425bb815Sopenharmony_ci 185425bb815Sopenharmony_ci if (context_p->token.type == LEXER_LITERAL 186425bb815Sopenharmony_ci && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) 187425bb815Sopenharmony_ci { 188425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; 189425bb815Sopenharmony_ci 190425bb815Sopenharmony_ci if (lexer_check_arrow (context_p)) 191425bb815Sopenharmony_ci { 192425bb815Sopenharmony_ci process_arrow = true; 193425bb815Sopenharmony_ci } 194425bb815Sopenharmony_ci else 195425bb815Sopenharmony_ci { 196425bb815Sopenharmony_ci lexer_lit_location_t *argument_literal_p = scanner_append_argument (context_p, scanner_context_p); 197425bb815Sopenharmony_ci 198425bb815Sopenharmony_ci scanner_detect_eval_call (context_p, scanner_context_p); 199425bb815Sopenharmony_ci 200425bb815Sopenharmony_ci lexer_next_token (context_p); 201425bb815Sopenharmony_ci 202425bb815Sopenharmony_ci if (context_p->token.type == LEXER_ASSIGN) 203425bb815Sopenharmony_ci { 204425bb815Sopenharmony_ci if (argument_literal_p->type & SCANNER_LITERAL_IS_USED) 205425bb815Sopenharmony_ci { 206425bb815Sopenharmony_ci JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE); 207425bb815Sopenharmony_ci return; 208425bb815Sopenharmony_ci } 209425bb815Sopenharmony_ci 210425bb815Sopenharmony_ci scanner_binding_literal_t binding_literal; 211425bb815Sopenharmony_ci binding_literal.literal_p = argument_literal_p; 212425bb815Sopenharmony_ci 213425bb815Sopenharmony_ci parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); 214425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); 215425bb815Sopenharmony_ci return; 216425bb815Sopenharmony_ci } 217425bb815Sopenharmony_ci 218425bb815Sopenharmony_ci if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN) 219425bb815Sopenharmony_ci { 220425bb815Sopenharmony_ci return; 221425bb815Sopenharmony_ci } 222425bb815Sopenharmony_ci } 223425bb815Sopenharmony_ci } 224425bb815Sopenharmony_ci else if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) 225425bb815Sopenharmony_ci { 226425bb815Sopenharmony_ci scanner_append_hole (context_p, scanner_context_p); 227425bb815Sopenharmony_ci scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false); 228425bb815Sopenharmony_ci 229425bb815Sopenharmony_ci if (context_p->token.type == LEXER_LEFT_BRACE) 230425bb815Sopenharmony_ci { 231425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); 232425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; 233425bb815Sopenharmony_ci return; 234425bb815Sopenharmony_ci } 235425bb815Sopenharmony_ci 236425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); 237425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_BINDING; 238425bb815Sopenharmony_ci lexer_next_token (context_p); 239425bb815Sopenharmony_ci return; 240425bb815Sopenharmony_ci } 241425bb815Sopenharmony_ci 242425bb815Sopenharmony_ci scanner_pop_literal_pool (context_p, scanner_context_p); 243425bb815Sopenharmony_ci 244425bb815Sopenharmony_ci parser_stack_pop_uint8 (context_p); 245425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); 246425bb815Sopenharmony_ci 247425bb815Sopenharmony_ci if (process_arrow) 248425bb815Sopenharmony_ci { 249425bb815Sopenharmony_ci scanner_scan_simple_arrow (context_p, scanner_context_p, source_p); 250425bb815Sopenharmony_ci } 251425bb815Sopenharmony_ci} /* scanner_check_arrow_arg */ 252425bb815Sopenharmony_ci 253425bb815Sopenharmony_ci/** 254425bb815Sopenharmony_ci * Detect async functions. 255425bb815Sopenharmony_ci * 256425bb815Sopenharmony_ci * @return true, if async is followed by a function keyword, false otherwise 257425bb815Sopenharmony_ci */ 258425bb815Sopenharmony_cibool 259425bb815Sopenharmony_ciscanner_check_async_function (parser_context_t *context_p, /**< context */ 260425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 261425bb815Sopenharmony_ci{ 262425bb815Sopenharmony_ci JERRY_ASSERT (lexer_token_is_async (context_p)); 263425bb815Sopenharmony_ci JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION 264425bb815Sopenharmony_ci || scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW); 265425bb815Sopenharmony_ci JERRY_ASSERT (scanner_context_p->async_source_p != NULL); 266425bb815Sopenharmony_ci 267425bb815Sopenharmony_ci lexer_lit_location_t async_literal = context_p->token.lit_location; 268425bb815Sopenharmony_ci 269425bb815Sopenharmony_ci lexer_next_token (context_p); 270425bb815Sopenharmony_ci 271425bb815Sopenharmony_ci if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) 272425bb815Sopenharmony_ci { 273425bb815Sopenharmony_ci if (context_p->token.type == LEXER_KEYW_FUNCTION) 274425bb815Sopenharmony_ci { 275425bb815Sopenharmony_ci return true; 276425bb815Sopenharmony_ci } 277425bb815Sopenharmony_ci 278425bb815Sopenharmony_ci if (context_p->token.type == LEXER_LITERAL 279425bb815Sopenharmony_ci && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) 280425bb815Sopenharmony_ci { 281425bb815Sopenharmony_ci if (!lexer_check_arrow (context_p)) 282425bb815Sopenharmony_ci { 283425bb815Sopenharmony_ci scanner_raise_error (context_p); 284425bb815Sopenharmony_ci } 285425bb815Sopenharmony_ci 286425bb815Sopenharmony_ci scanner_scan_simple_arrow (context_p, scanner_context_p, scanner_context_p->async_source_p); 287425bb815Sopenharmony_ci scanner_context_p->async_source_p = NULL; 288425bb815Sopenharmony_ci return false; 289425bb815Sopenharmony_ci } 290425bb815Sopenharmony_ci 291425bb815Sopenharmony_ci if (context_p->token.type == LEXER_LEFT_PAREN) 292425bb815Sopenharmony_ci { 293425bb815Sopenharmony_ci parser_stack_push (context_p, &async_literal, sizeof (lexer_lit_location_t)); 294425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_USE_ASYNC); 295425bb815Sopenharmony_ci return false; 296425bb815Sopenharmony_ci } 297425bb815Sopenharmony_ci } 298425bb815Sopenharmony_ci 299425bb815Sopenharmony_ci lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p, 300425bb815Sopenharmony_ci scanner_context_p->active_literal_pool_p, 301425bb815Sopenharmony_ci &async_literal); 302425bb815Sopenharmony_ci lit_location_p->type |= SCANNER_LITERAL_IS_USED; 303425bb815Sopenharmony_ci 304425bb815Sopenharmony_ci if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) 305425bb815Sopenharmony_ci { 306425bb815Sopenharmony_ci lit_location_p->type |= SCANNER_LITERAL_NO_REG; 307425bb815Sopenharmony_ci } 308425bb815Sopenharmony_ci 309425bb815Sopenharmony_ci scanner_context_p->async_source_p = NULL; 310425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; 311425bb815Sopenharmony_ci return false; 312425bb815Sopenharmony_ci} /* scanner_check_async_function */ 313425bb815Sopenharmony_ci 314425bb815Sopenharmony_ci/** 315425bb815Sopenharmony_ci * Check whether the statement of an if/else construct is a function statement. 316425bb815Sopenharmony_ci */ 317425bb815Sopenharmony_civoid 318425bb815Sopenharmony_ciscanner_check_function_after_if (parser_context_t *context_p, /**< context */ 319425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 320425bb815Sopenharmony_ci{ 321425bb815Sopenharmony_ci lexer_next_token (context_p); 322425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_STATEMENT; 323425bb815Sopenharmony_ci 324425bb815Sopenharmony_ci if (JERRY_UNLIKELY (context_p->token.type == LEXER_KEYW_FUNCTION)) 325425bb815Sopenharmony_ci { 326425bb815Sopenharmony_ci scanner_literal_pool_t *literal_pool_p; 327425bb815Sopenharmony_ci literal_pool_p = scanner_push_literal_pool (context_p, 328425bb815Sopenharmony_ci scanner_context_p, 329425bb815Sopenharmony_ci SCANNER_LITERAL_POOL_BLOCK); 330425bb815Sopenharmony_ci 331425bb815Sopenharmony_ci literal_pool_p->source_p = context_p->source_p; 332425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK); 333425bb815Sopenharmony_ci } 334425bb815Sopenharmony_ci} /* scanner_check_function_after_if */ 335425bb815Sopenharmony_ci 336425bb815Sopenharmony_ci/** 337425bb815Sopenharmony_ci * Arrow types for scanner_scan_bracket() function. 338425bb815Sopenharmony_ci */ 339425bb815Sopenharmony_citypedef enum 340425bb815Sopenharmony_ci{ 341425bb815Sopenharmony_ci SCANNER_SCAN_BRACKET_NO_ARROW, /**< not an arrow function */ 342425bb815Sopenharmony_ci SCANNER_SCAN_BRACKET_SIMPLE_ARROW, /**< simple arrow function */ 343425bb815Sopenharmony_ci SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG, /**< arrow function with one argument */ 344425bb815Sopenharmony_ci} scanner_scan_bracket_arrow_type_t; 345425bb815Sopenharmony_ci 346425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 347425bb815Sopenharmony_ci 348425bb815Sopenharmony_ci/** 349425bb815Sopenharmony_ci * Scan bracketed expressions. 350425bb815Sopenharmony_ci */ 351425bb815Sopenharmony_civoid 352425bb815Sopenharmony_ciscanner_scan_bracket (parser_context_t *context_p, /**< context */ 353425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 354425bb815Sopenharmony_ci{ 355425bb815Sopenharmony_ci size_t depth = 0; 356425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 357425bb815Sopenharmony_ci const uint8_t *arrow_source_p; 358425bb815Sopenharmony_ci const uint8_t *async_source_p = NULL; 359425bb815Sopenharmony_ci scanner_scan_bracket_arrow_type_t arrow_type = SCANNER_SCAN_BRACKET_NO_ARROW; 360425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 361425bb815Sopenharmony_ci 362425bb815Sopenharmony_ci JERRY_ASSERT (context_p->token.type == LEXER_LEFT_PAREN); 363425bb815Sopenharmony_ci 364425bb815Sopenharmony_ci do 365425bb815Sopenharmony_ci { 366425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 367425bb815Sopenharmony_ci arrow_source_p = context_p->source_p; 368425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 369425bb815Sopenharmony_ci depth++; 370425bb815Sopenharmony_ci lexer_next_token (context_p); 371425bb815Sopenharmony_ci } 372425bb815Sopenharmony_ci while (context_p->token.type == LEXER_LEFT_PAREN); 373425bb815Sopenharmony_ci 374425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; 375425bb815Sopenharmony_ci 376425bb815Sopenharmony_ci switch (context_p->token.type) 377425bb815Sopenharmony_ci { 378425bb815Sopenharmony_ci case LEXER_LITERAL: 379425bb815Sopenharmony_ci { 380425bb815Sopenharmony_ci if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) 381425bb815Sopenharmony_ci { 382425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 383425bb815Sopenharmony_ci arrow_source_p = NULL; 384425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 385425bb815Sopenharmony_ci break; 386425bb815Sopenharmony_ci } 387425bb815Sopenharmony_ci 388425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 389425bb815Sopenharmony_ci const uint8_t *source_p = context_p->source_p; 390425bb815Sopenharmony_ci 391425bb815Sopenharmony_ci if (lexer_check_arrow (context_p)) 392425bb815Sopenharmony_ci { 393425bb815Sopenharmony_ci arrow_source_p = source_p; 394425bb815Sopenharmony_ci arrow_type = SCANNER_SCAN_BRACKET_SIMPLE_ARROW; 395425bb815Sopenharmony_ci break; 396425bb815Sopenharmony_ci } 397425bb815Sopenharmony_ci 398425bb815Sopenharmony_ci size_t total_depth = depth; 399425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 400425bb815Sopenharmony_ci 401425bb815Sopenharmony_ci while (depth > 0 && lexer_check_next_character (context_p, LIT_CHAR_RIGHT_PAREN)) 402425bb815Sopenharmony_ci { 403425bb815Sopenharmony_ci lexer_consume_next_character (context_p); 404425bb815Sopenharmony_ci depth--; 405425bb815Sopenharmony_ci } 406425bb815Sopenharmony_ci 407425bb815Sopenharmony_ci if (context_p->token.keyword_type == LEXER_KEYW_EVAL 408425bb815Sopenharmony_ci && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) 409425bb815Sopenharmony_ci { 410425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 411425bb815Sopenharmony_ci /* A function call cannot be an eval function. */ 412425bb815Sopenharmony_ci arrow_source_p = NULL; 413425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 414425bb815Sopenharmony_ci 415425bb815Sopenharmony_ci scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL; 416425bb815Sopenharmony_ci break; 417425bb815Sopenharmony_ci } 418425bb815Sopenharmony_ci 419425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 420425bb815Sopenharmony_ci if (total_depth == depth) 421425bb815Sopenharmony_ci { 422425bb815Sopenharmony_ci if (lexer_check_arrow_param (context_p)) 423425bb815Sopenharmony_ci { 424425bb815Sopenharmony_ci JERRY_ASSERT (depth > 0); 425425bb815Sopenharmony_ci depth--; 426425bb815Sopenharmony_ci break; 427425bb815Sopenharmony_ci } 428425bb815Sopenharmony_ci 429425bb815Sopenharmony_ci if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) 430425bb815Sopenharmony_ci { 431425bb815Sopenharmony_ci async_source_p = source_p; 432425bb815Sopenharmony_ci } 433425bb815Sopenharmony_ci } 434425bb815Sopenharmony_ci else if (depth == total_depth - 1) 435425bb815Sopenharmony_ci { 436425bb815Sopenharmony_ci if (lexer_check_arrow (context_p)) 437425bb815Sopenharmony_ci { 438425bb815Sopenharmony_ci arrow_type = SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG; 439425bb815Sopenharmony_ci break; 440425bb815Sopenharmony_ci } 441425bb815Sopenharmony_ci 442425bb815Sopenharmony_ci if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) 443425bb815Sopenharmony_ci { 444425bb815Sopenharmony_ci scanner_add_async_literal (context_p, scanner_context_p); 445425bb815Sopenharmony_ci } 446425bb815Sopenharmony_ci } 447425bb815Sopenharmony_ci 448425bb815Sopenharmony_ci arrow_source_p = NULL; 449425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 450425bb815Sopenharmony_ci break; 451425bb815Sopenharmony_ci } 452425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 453425bb815Sopenharmony_ci case LEXER_THREE_DOTS: 454425bb815Sopenharmony_ci case LEXER_LEFT_SQUARE: 455425bb815Sopenharmony_ci case LEXER_LEFT_BRACE: 456425bb815Sopenharmony_ci case LEXER_RIGHT_PAREN: 457425bb815Sopenharmony_ci { 458425bb815Sopenharmony_ci JERRY_ASSERT (depth > 0); 459425bb815Sopenharmony_ci depth--; 460425bb815Sopenharmony_ci break; 461425bb815Sopenharmony_ci } 462425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 463425bb815Sopenharmony_ci default: 464425bb815Sopenharmony_ci { 465425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 466425bb815Sopenharmony_ci arrow_source_p = NULL; 467425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 468425bb815Sopenharmony_ci break; 469425bb815Sopenharmony_ci } 470425bb815Sopenharmony_ci } 471425bb815Sopenharmony_ci 472425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 473425bb815Sopenharmony_ci if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL) 474425bb815Sopenharmony_ci && (arrow_source_p == NULL || depth > 0)) 475425bb815Sopenharmony_ci { 476425bb815Sopenharmony_ci scanner_context_p->async_source_p = NULL; 477425bb815Sopenharmony_ci } 478425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 479425bb815Sopenharmony_ci 480425bb815Sopenharmony_ci while (depth > 0) 481425bb815Sopenharmony_ci { 482425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); 483425bb815Sopenharmony_ci depth--; 484425bb815Sopenharmony_ci } 485425bb815Sopenharmony_ci 486425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 487425bb815Sopenharmony_ci if (arrow_source_p != NULL) 488425bb815Sopenharmony_ci { 489425bb815Sopenharmony_ci JERRY_ASSERT (async_source_p == NULL); 490425bb815Sopenharmony_ci 491425bb815Sopenharmony_ci if (arrow_type == SCANNER_SCAN_BRACKET_SIMPLE_ARROW) 492425bb815Sopenharmony_ci { 493425bb815Sopenharmony_ci scanner_scan_simple_arrow (context_p, scanner_context_p, arrow_source_p); 494425bb815Sopenharmony_ci return; 495425bb815Sopenharmony_ci } 496425bb815Sopenharmony_ci 497425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_ARGUMENTS); 498425bb815Sopenharmony_ci 499425bb815Sopenharmony_ci uint16_t status_flags = 0; 500425bb815Sopenharmony_ci 501425bb815Sopenharmony_ci if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL)) 502425bb815Sopenharmony_ci { 503425bb815Sopenharmony_ci status_flags |= SCANNER_LITERAL_POOL_ASYNC_ARROW; 504425bb815Sopenharmony_ci arrow_source_p = scanner_context_p->async_source_p; 505425bb815Sopenharmony_ci scanner_context_p->async_source_p = NULL; 506425bb815Sopenharmony_ci } 507425bb815Sopenharmony_ci 508425bb815Sopenharmony_ci scanner_literal_pool_t *literal_pool_p; 509425bb815Sopenharmony_ci literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags); 510425bb815Sopenharmony_ci literal_pool_p->source_p = arrow_source_p; 511425bb815Sopenharmony_ci 512425bb815Sopenharmony_ci if (arrow_type == SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG) 513425bb815Sopenharmony_ci { 514425bb815Sopenharmony_ci scanner_append_argument (context_p, scanner_context_p); 515425bb815Sopenharmony_ci scanner_detect_eval_call (context_p, scanner_context_p); 516425bb815Sopenharmony_ci 517425bb815Sopenharmony_ci context_p->token.type = LEXER_RIGHT_PAREN; 518425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; 519425bb815Sopenharmony_ci } 520425bb815Sopenharmony_ci else if (context_p->token.type == LEXER_RIGHT_PAREN) 521425bb815Sopenharmony_ci { 522425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; 523425bb815Sopenharmony_ci } 524425bb815Sopenharmony_ci else 525425bb815Sopenharmony_ci { 526425bb815Sopenharmony_ci scanner_check_arrow_arg (context_p, scanner_context_p); 527425bb815Sopenharmony_ci } 528425bb815Sopenharmony_ci } 529425bb815Sopenharmony_ci else if (JERRY_UNLIKELY (async_source_p != NULL)) 530425bb815Sopenharmony_ci { 531425bb815Sopenharmony_ci scanner_context_p->async_source_p = async_source_p; 532425bb815Sopenharmony_ci scanner_check_async_function (context_p, scanner_context_p); 533425bb815Sopenharmony_ci } 534425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 535425bb815Sopenharmony_ci} /* scanner_scan_bracket */ 536425bb815Sopenharmony_ci 537425bb815Sopenharmony_ci/** 538425bb815Sopenharmony_ci * Check directives before a source block. 539425bb815Sopenharmony_ci */ 540425bb815Sopenharmony_civoid 541425bb815Sopenharmony_ciscanner_check_directives (parser_context_t *context_p, /**< context */ 542425bb815Sopenharmony_ci scanner_context_t *scanner_context_p) /**< scanner context */ 543425bb815Sopenharmony_ci{ 544425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; 545425bb815Sopenharmony_ci 546425bb815Sopenharmony_ci while (context_p->token.type == LEXER_LITERAL 547425bb815Sopenharmony_ci && context_p->token.lit_location.type == LEXER_STRING_LITERAL) 548425bb815Sopenharmony_ci { 549425bb815Sopenharmony_ci bool is_use_strict = false; 550425bb815Sopenharmony_ci 551425bb815Sopenharmony_ci if (lexer_string_is_use_strict (context_p) 552425bb815Sopenharmony_ci && !(context_p->status_flags & PARSER_IS_STRICT)) 553425bb815Sopenharmony_ci { 554425bb815Sopenharmony_ci is_use_strict = true; 555425bb815Sopenharmony_ci context_p->status_flags |= PARSER_IS_STRICT; 556425bb815Sopenharmony_ci } 557425bb815Sopenharmony_ci 558425bb815Sopenharmony_ci lexer_next_token (context_p); 559425bb815Sopenharmony_ci 560425bb815Sopenharmony_ci if (!lexer_string_is_directive (context_p)) 561425bb815Sopenharmony_ci { 562425bb815Sopenharmony_ci if (is_use_strict) 563425bb815Sopenharmony_ci { 564425bb815Sopenharmony_ci context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; 565425bb815Sopenharmony_ci } 566425bb815Sopenharmony_ci 567425bb815Sopenharmony_ci /* The string is part of an expression statement. */ 568425bb815Sopenharmony_ci scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; 569425bb815Sopenharmony_ci break; 570425bb815Sopenharmony_ci } 571425bb815Sopenharmony_ci 572425bb815Sopenharmony_ci if (is_use_strict) 573425bb815Sopenharmony_ci { 574425bb815Sopenharmony_ci scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; 575425bb815Sopenharmony_ci } 576425bb815Sopenharmony_ci 577425bb815Sopenharmony_ci if (context_p->token.type == LEXER_SEMICOLON) 578425bb815Sopenharmony_ci { 579425bb815Sopenharmony_ci lexer_next_token (context_p); 580425bb815Sopenharmony_ci } 581425bb815Sopenharmony_ci } 582425bb815Sopenharmony_ci} /* scanner_check_directives */ 583425bb815Sopenharmony_ci 584425bb815Sopenharmony_ci/** 585425bb815Sopenharmony_ci * @} 586425bb815Sopenharmony_ci * @} 587425bb815Sopenharmony_ci * @} 588425bb815Sopenharmony_ci */ 589425bb815Sopenharmony_ci 590425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER) */ 591