1 /* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "jcontext.h"
17 #include "js-parser-internal.h"
18 #include "js-scanner-internal.h"
19 #include "lit-char-helpers.h"
20
21 #if ENABLED (JERRY_PARSER)
22
23 /** \addtogroup parser Parser
24 * @{
25 *
26 * \addtogroup jsparser JavaScript
27 * @{
28 *
29 * \addtogroup jsparser_scanner Scanner
30 * @{
31 */
32
33 /**
34 * Scan return types.
35 */
36 typedef enum
37 {
38 SCAN_NEXT_TOKEN, /**< get next token after return */
39 SCAN_KEEP_TOKEN, /**< keep the current token after return */
40 } scan_return_types_t;
41
42 /**
43 * Checks whether token type is "of".
44 */
45 #if ENABLED (JERRY_ES2015)
46 #define SCANNER_IDENTIFIER_IS_OF() (lexer_token_is_identifier (context_p, "of", 2))
47 #else
48 #define SCANNER_IDENTIFIER_IS_OF() (false)
49 #endif /* ENABLED (JERRY_ES2015) */
50
51 #if ENABLED (JERRY_ES2015)
52
53 JERRY_STATIC_ASSERT (SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_GENERATOR)
54 == SCAN_STACK_COMPUTED_GENERATOR,
55 scanner_invalid_conversion_from_literal_pool_generator_to_computed_generator);
56 JERRY_STATIC_ASSERT (SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_ASYNC)
57 == SCAN_STACK_COMPUTED_ASYNC,
58 scanner_invalid_conversion_from_literal_pool_async_to_computed_async);
59
60 JERRY_STATIC_ASSERT (SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_GENERATOR)
61 == SCANNER_LITERAL_POOL_GENERATOR,
62 scanner_invalid_conversion_from_computed_generator_to_literal_pool_generator);
63 JERRY_STATIC_ASSERT (SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_ASYNC)
64 == SCANNER_LITERAL_POOL_ASYNC,
65 scanner_invalid_conversion_from_computed_async_to_literal_pool_async);
66
67 #endif /* ENABLED (JERRY_ES2015) */
68
69 /**
70 * Scan primary expression.
71 *
72 * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
73 */
74 static scan_return_types_t
scanner_scan_primary_expression(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_token_type_t type,scan_stack_modes_t stack_top)75 scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
76 scanner_context_t *scanner_context_p, /* scanner context */
77 lexer_token_type_t type, /**< current token type */
78 scan_stack_modes_t stack_top) /**< current stack top */
79 {
80 switch (type)
81 {
82 case LEXER_KEYW_NEW:
83 {
84 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW;
85
86 #if ENABLED (JERRY_ES2015)
87 if (scanner_try_scan_new_target (context_p))
88 {
89 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
90 }
91 #endif /* ENABLED (JERRY_ES2015) */
92 break;
93 }
94 case LEXER_DIVIDE:
95 case LEXER_ASSIGN_DIVIDE:
96 {
97 lexer_construct_regexp_object (context_p, true);
98 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
99 break;
100 }
101 case LEXER_KEYW_FUNCTION:
102 {
103 uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
104
105 #if ENABLED (JERRY_ES2015)
106 if (scanner_context_p->async_source_p != NULL)
107 {
108 status_flags |= SCANNER_LITERAL_POOL_ASYNC;
109 }
110
111 if (lexer_consume_generator (context_p))
112 {
113 status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
114 }
115 #endif /* ENABLED (JERRY_ES2015) */
116
117 scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
118
119 lexer_next_token (context_p);
120
121 if (context_p->token.type == LEXER_LITERAL
122 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
123 {
124 lexer_next_token (context_p);
125 }
126
127 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
128 scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
129 return SCAN_KEEP_TOKEN;
130 }
131 case LEXER_LEFT_PAREN:
132 {
133 scanner_scan_bracket (context_p, scanner_context_p);
134 return SCAN_KEEP_TOKEN;
135 }
136 case LEXER_LEFT_SQUARE:
137 {
138 #if ENABLED (JERRY_ES2015)
139 scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false);
140 #endif /* ENABLED (JERRY_ES2015) */
141
142 parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
143 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
144 break;
145 }
146 case LEXER_LEFT_BRACE:
147 {
148 #if ENABLED (JERRY_ES2015)
149 scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false);
150 #endif /* ENABLED (JERRY_ES2015) */
151
152 parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
153 scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
154 return SCAN_KEEP_TOKEN;
155 }
156 #if ENABLED (JERRY_ES2015)
157 case LEXER_TEMPLATE_LITERAL:
158 {
159 if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
160 {
161 parser_stack_push_uint8 (context_p, SCAN_STACK_TEMPLATE_STRING);
162 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
163 break;
164 }
165
166 /* The string is a normal string literal. */
167 /* FALLTHRU */
168 }
169 #endif /* ENABLED (JERRY_ES2015) */
170 case LEXER_LITERAL:
171 {
172 #if ENABLED (JERRY_ES2015)
173 const uint8_t *source_p = context_p->source_p;
174
175 if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
176 && lexer_check_arrow (context_p))
177 {
178 scanner_scan_simple_arrow (context_p, scanner_context_p, source_p);
179 return SCAN_KEEP_TOKEN;
180 }
181 else if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
182 {
183 scanner_context_p->async_source_p = source_p;
184 scanner_check_async_function (context_p, scanner_context_p);
185 return SCAN_KEEP_TOKEN;
186 }
187 #endif /* ENABLED (JERRY_ES2015) */
188
189 if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
190 {
191 scanner_add_reference (context_p, scanner_context_p);
192 }
193 /* FALLTHRU */
194 }
195 case LEXER_KEYW_THIS:
196 case LEXER_KEYW_SUPER:
197 case LEXER_LIT_TRUE:
198 case LEXER_LIT_FALSE:
199 case LEXER_LIT_NULL:
200 {
201 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
202 break;
203 }
204 #if ENABLED (JERRY_ES2015)
205 case LEXER_KEYW_CLASS:
206 {
207 scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_EXPRESSION);
208
209 if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
210 {
211 return SCAN_KEEP_TOKEN;
212 }
213 break;
214 }
215 #endif /* ENABLED (JERRY_ES2015) */
216 case LEXER_RIGHT_SQUARE:
217 {
218 if (stack_top != SCAN_STACK_ARRAY_LITERAL)
219 {
220 scanner_raise_error (context_p);
221 }
222
223 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
224 return SCAN_KEEP_TOKEN;
225 }
226 #if ENABLED (JERRY_ES2015)
227 case LEXER_THREE_DOTS:
228 {
229 /* Elision or spread arguments */
230 if (stack_top != SCAN_STACK_PAREN_EXPRESSION && stack_top != SCAN_STACK_ARRAY_LITERAL)
231 {
232 scanner_raise_error (context_p);
233 }
234 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
235 break;
236 }
237 #endif /* ENABLED (JERRY_ES2015) */
238 case LEXER_COMMA:
239 {
240 if (stack_top != SCAN_STACK_ARRAY_LITERAL)
241 {
242 scanner_raise_error (context_p);
243 }
244 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
245
246 #if ENABLED (JERRY_ES2015)
247 if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
248 {
249 scanner_context_p->mode = SCAN_MODE_BINDING;
250 }
251 #endif /* ENABLED (JERRY_ES2015) */
252 break;
253 }
254 #if ENABLED (JERRY_ES2015)
255 case LEXER_KEYW_YIELD:
256 {
257 lexer_next_token (context_p);
258
259 if (lexer_check_yield_no_arg (context_p))
260 {
261 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
262 }
263
264 if (context_p->token.type == LEXER_MULTIPLY)
265 {
266 return SCAN_NEXT_TOKEN;
267 }
268 return SCAN_KEEP_TOKEN;
269 }
270 #endif /* ENABLED (JERRY_ES2015) */
271 case LEXER_RIGHT_PAREN:
272 {
273 if (stack_top == SCAN_STACK_PAREN_EXPRESSION)
274 {
275 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
276 parser_stack_pop_uint8 (context_p);
277 break;
278 }
279 /* FALLTHRU */
280 }
281 default:
282 {
283 scanner_raise_error (context_p);
284 }
285 }
286 return SCAN_NEXT_TOKEN;
287 } /* scanner_scan_primary_expression */
288
289 /**
290 * Scan the tokens after the primary expression.
291 *
292 * @return true for break, false for fall through
293 */
294 static bool
scanner_scan_post_primary_expression(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_token_type_t type,scan_stack_modes_t stack_top)295 scanner_scan_post_primary_expression (parser_context_t *context_p, /**< context */
296 scanner_context_t *scanner_context_p, /**< scanner context */
297 lexer_token_type_t type, /**< current token type */
298 scan_stack_modes_t stack_top) /**< current stack top */
299 {
300 switch (type)
301 {
302 case LEXER_DOT:
303 {
304 lexer_scan_identifier (context_p);
305
306 if (context_p->token.type != LEXER_LITERAL
307 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
308 {
309 scanner_raise_error (context_p);
310 }
311
312 return true;
313 }
314 case LEXER_LEFT_PAREN:
315 {
316 parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
317 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
318 return true;
319 }
320 #if ENABLED (JERRY_ES2015)
321 case LEXER_TEMPLATE_LITERAL:
322 {
323 if (JERRY_UNLIKELY (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT))
324 {
325 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
326 parser_stack_push_uint8 (context_p, SCAN_STACK_TAGGED_TEMPLATE_LITERAL);
327 }
328 return true;
329 }
330 #endif /* ENABLED (JERRY_ES2015) */
331 case LEXER_LEFT_SQUARE:
332 {
333 parser_stack_push_uint8 (context_p, SCAN_STACK_PROPERTY_ACCESSOR);
334 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
335 return true;
336 }
337 case LEXER_INCREASE:
338 case LEXER_DECREASE:
339 {
340 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
341
342 if (context_p->token.flags & LEXER_WAS_NEWLINE)
343 {
344 return false;
345 }
346
347 lexer_next_token (context_p);
348 type = (lexer_token_type_t) context_p->token.type;
349
350 if (type != LEXER_QUESTION_MARK)
351 {
352 break;
353 }
354 /* FALLTHRU */
355 }
356 case LEXER_QUESTION_MARK:
357 {
358 parser_stack_push_uint8 (context_p, SCAN_STACK_COLON_EXPRESSION);
359 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
360 return true;
361 }
362 default:
363 {
364 break;
365 }
366 }
367
368 if (LEXER_IS_BINARY_OP_TOKEN (type)
369 && (type != LEXER_KEYW_IN || !SCANNER_IS_FOR_START (stack_top)))
370 {
371 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
372 return true;
373 }
374
375 return false;
376 } /* scanner_scan_post_primary_expression */
377
378 /**
379 * Scan the tokens after the primary expression.
380 *
381 * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
382 */
383 static scan_return_types_t
scanner_scan_primary_expression_end(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_token_type_t type,scan_stack_modes_t stack_top)384 scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context */
385 scanner_context_t *scanner_context_p, /**< scanner context */
386 lexer_token_type_t type, /**< current token type */
387 scan_stack_modes_t stack_top) /**< current stack top */
388 {
389 if (type == LEXER_COMMA)
390 {
391 switch (stack_top)
392 {
393 case SCAN_STACK_VAR:
394 #if ENABLED (JERRY_ES2015)
395 case SCAN_STACK_LET:
396 case SCAN_STACK_CONST:
397 #endif /* ENABLED (JERRY_ES2015) */
398 case SCAN_STACK_FOR_VAR_START:
399 #if ENABLED (JERRY_ES2015)
400 case SCAN_STACK_FOR_LET_START:
401 case SCAN_STACK_FOR_CONST_START:
402 #endif /* ENABLED (JERRY_ES2015) */
403 {
404 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
405 return SCAN_NEXT_TOKEN;
406 }
407 case SCAN_STACK_COLON_EXPRESSION:
408 {
409 scanner_raise_error (context_p);
410 break;
411 }
412 #if ENABLED (JERRY_ES2015)
413 case SCAN_STACK_BINDING_INIT:
414 case SCAN_STACK_BINDING_LIST_INIT:
415 {
416 break;
417 }
418 case SCAN_STACK_ARROW_ARGUMENTS:
419 {
420 lexer_next_token (context_p);
421 scanner_check_arrow_arg (context_p, scanner_context_p);
422 return SCAN_KEEP_TOKEN;
423 }
424 case SCAN_STACK_ARROW_EXPRESSION:
425 {
426 break;
427 }
428 case SCAN_STACK_FUNCTION_PARAMETERS:
429 {
430 scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
431 parser_stack_pop_uint8 (context_p);
432 return SCAN_NEXT_TOKEN;
433 }
434 case SCAN_STACK_ARRAY_LITERAL:
435 {
436 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
437
438 if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
439 {
440 scanner_context_p->mode = SCAN_MODE_BINDING;
441 }
442
443 return SCAN_NEXT_TOKEN;
444 }
445 #endif /* ENABLED (JERRY_ES2015) */
446 case SCAN_STACK_OBJECT_LITERAL:
447 {
448 scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
449 return SCAN_KEEP_TOKEN;
450 }
451 default:
452 {
453 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
454 return SCAN_NEXT_TOKEN;
455 }
456 }
457 }
458
459 switch (stack_top)
460 {
461 case SCAN_STACK_WITH_EXPRESSION:
462 {
463 if (type != LEXER_RIGHT_PAREN)
464 {
465 break;
466 }
467
468 parser_stack_pop_uint8 (context_p);
469
470 uint16_t status_flags = scanner_context_p->active_literal_pool_p->status_flags;
471 parser_stack_push_uint8 (context_p, (status_flags & SCANNER_LITERAL_POOL_IN_WITH) ? 1 : 0);
472 parser_stack_push_uint8 (context_p, SCAN_STACK_WITH_STATEMENT);
473 status_flags |= SCANNER_LITERAL_POOL_IN_WITH;
474 scanner_context_p->active_literal_pool_p->status_flags = status_flags;
475
476 scanner_context_p->mode = SCAN_MODE_STATEMENT;
477 return SCAN_NEXT_TOKEN;
478 }
479 case SCAN_STACK_DO_EXPRESSION:
480 {
481 if (type != LEXER_RIGHT_PAREN)
482 {
483 break;
484 }
485
486 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
487 return SCAN_NEXT_TOKEN;
488 }
489 case SCAN_STACK_WHILE_EXPRESSION:
490 {
491 if (type != LEXER_RIGHT_PAREN)
492 {
493 break;
494 }
495
496 scanner_source_start_t source_start;
497
498 parser_stack_pop_uint8 (context_p);
499 parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
500
501 scanner_location_info_t *location_info_p;
502 location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
503 source_start.source_p,
504 sizeof (scanner_location_info_t));
505 location_info_p->info.type = SCANNER_TYPE_WHILE;
506
507 scanner_get_location (&location_info_p->location, context_p);
508
509 scanner_context_p->mode = SCAN_MODE_STATEMENT;
510 return SCAN_NEXT_TOKEN;
511 }
512 case SCAN_STACK_PAREN_EXPRESSION:
513 {
514 if (type != LEXER_RIGHT_PAREN)
515 {
516 break;
517 }
518
519 parser_stack_pop_uint8 (context_p);
520
521 #if ENABLED (JERRY_ES2015)
522 if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
523 {
524 scanner_add_async_literal (context_p, scanner_context_p);
525 }
526 #endif /* ENABLED (JERRY_ES2015) */
527
528 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
529 return SCAN_NEXT_TOKEN;
530 }
531 case SCAN_STACK_STATEMENT_WITH_EXPR:
532 {
533 if (type != LEXER_RIGHT_PAREN)
534 {
535 break;
536 }
537
538 parser_stack_pop_uint8 (context_p);
539
540 #if ENABLED (JERRY_ES2015)
541 if (context_p->stack_top_uint8 == SCAN_STACK_IF_STATEMENT)
542 {
543 scanner_check_function_after_if (context_p, scanner_context_p);
544 return SCAN_KEEP_TOKEN;
545 }
546 #endif /* ENABLED (JERRY_ES2015) */
547
548 scanner_context_p->mode = SCAN_MODE_STATEMENT;
549 return SCAN_NEXT_TOKEN;
550 }
551 #if ENABLED (JERRY_ES2015)
552 case SCAN_STACK_BINDING_LIST_INIT:
553 {
554 parser_stack_pop_uint8 (context_p);
555
556 JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
557 || context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
558 || context_p->stack_top_uint8 == SCAN_STACK_LET
559 || context_p->stack_top_uint8 == SCAN_STACK_CONST
560 || context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
561 || context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START
562 || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS
563 || context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
564
565 scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p;
566
567 while (item_p != NULL)
568 {
569 if (item_p->literal_p->type & SCANNER_LITERAL_IS_USED)
570 {
571 item_p->literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
572 }
573 item_p = item_p->next_p;
574 }
575
576 scanner_pop_binding_list (scanner_context_p);
577 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
578 return SCAN_KEEP_TOKEN;
579 }
580 case SCAN_STACK_BINDING_INIT:
581 {
582 scanner_binding_literal_t binding_literal;
583
584 parser_stack_pop_uint8 (context_p);
585 parser_stack_pop (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
586
587 JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
588 || context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
589 || context_p->stack_top_uint8 == SCAN_STACK_LET
590 || context_p->stack_top_uint8 == SCAN_STACK_CONST
591 || context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
592 || context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START
593 || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS
594 || context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
595
596 JERRY_ASSERT ((stack_top != SCAN_STACK_ARRAY_LITERAL && stack_top != SCAN_STACK_OBJECT_LITERAL)
597 || SCANNER_NEEDS_BINDING_LIST (scanner_context_p->binding_type));
598
599 if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED)
600 {
601 binding_literal.literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
602 }
603
604 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
605 return SCAN_KEEP_TOKEN;
606 }
607 #endif /* ENABLED (JERRY_ES2015) */
608 case SCAN_STACK_VAR:
609 #if ENABLED (JERRY_ES2015)
610 case SCAN_STACK_LET:
611 case SCAN_STACK_CONST:
612 #endif /* ENABLED (JERRY_ES2015) */
613 {
614 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
615 scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
616 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
617
618 parser_stack_pop_uint8 (context_p);
619 return SCAN_KEEP_TOKEN;
620 }
621 case SCAN_STACK_FOR_VAR_START:
622 #if ENABLED (JERRY_ES2015)
623 case SCAN_STACK_FOR_LET_START:
624 case SCAN_STACK_FOR_CONST_START:
625 #endif /* ENABLED (JERRY_ES2015) */
626 case SCAN_STACK_FOR_START:
627 {
628 if (type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ())
629 {
630 scanner_for_statement_t for_statement;
631
632 parser_stack_pop_uint8 (context_p);
633 parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t));
634
635 scanner_location_info_t *location_info;
636 location_info = (scanner_location_info_t *) scanner_insert_info (context_p,
637 for_statement.u.source_p,
638 sizeof (scanner_location_info_t));
639 #if ENABLED (JERRY_ES2015)
640 location_info->info.type = (type == LEXER_KEYW_IN) ? SCANNER_TYPE_FOR_IN : SCANNER_TYPE_FOR_OF;
641
642 if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START)
643 {
644 parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK_EARLY);
645 }
646 #else /* !ENABLED (JERRY_ES2015) */
647 location_info->info.type = SCANNER_TYPE_FOR_IN;
648 #endif /* ENABLED (JERRY_ES2015) */
649
650 scanner_get_location (&location_info->location, context_p);
651
652 parser_stack_push_uint8 (context_p, SCAN_STACK_STATEMENT_WITH_EXPR);
653 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
654 return SCAN_NEXT_TOKEN;
655 }
656
657 if (type != LEXER_SEMICOLON)
658 {
659 break;
660 }
661
662 scanner_for_statement_t for_statement;
663
664 parser_stack_pop_uint8 (context_p);
665 parser_stack_pop (context_p, NULL, sizeof (scanner_for_statement_t));
666
667 #if ENABLED (JERRY_ES2015)
668 if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START)
669 {
670 parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK);
671 }
672 #endif /* ENABLED (JERRY_ES2015) */
673
674 for_statement.u.source_p = context_p->source_p;
675 parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t));
676 parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_CONDITION);
677
678 lexer_next_token (context_p);
679
680 if (context_p->token.type != LEXER_SEMICOLON)
681 {
682 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
683 return SCAN_KEEP_TOKEN;
684 }
685
686 type = LEXER_SEMICOLON;
687 /* FALLTHRU */
688 }
689 case SCAN_STACK_FOR_CONDITION:
690 {
691 if (type != LEXER_SEMICOLON)
692 {
693 break;
694 }
695
696 scanner_for_statement_t for_statement;
697
698 parser_stack_pop_uint8 (context_p);
699 parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t));
700
701 scanner_for_info_t *for_info_p;
702 for_info_p = (scanner_for_info_t *) scanner_insert_info (context_p,
703 for_statement.u.source_p,
704 sizeof (scanner_for_info_t));
705 for_info_p->info.type = SCANNER_TYPE_FOR;
706
707 scanner_get_location (&for_info_p->expression_location, context_p);
708 for_info_p->end_location.source_p = NULL;
709
710 for_statement.u.for_info_p = for_info_p;
711
712 parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t));
713 parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_EXPRESSION);
714
715 lexer_next_token (context_p);
716
717 if (context_p->token.type != LEXER_RIGHT_PAREN)
718 {
719 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
720 return SCAN_KEEP_TOKEN;
721 }
722
723 type = LEXER_RIGHT_PAREN;
724 /* FALLTHRU */
725 }
726 case SCAN_STACK_FOR_EXPRESSION:
727 {
728 if (type != LEXER_RIGHT_PAREN)
729 {
730 break;
731 }
732
733 scanner_for_statement_t for_statement;
734
735 parser_stack_pop_uint8 (context_p);
736 parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t));
737
738 scanner_get_location (&for_statement.u.for_info_p->end_location, context_p);
739
740 scanner_context_p->mode = SCAN_MODE_STATEMENT;
741 return SCAN_NEXT_TOKEN;
742 }
743 case SCAN_STACK_SWITCH_EXPRESSION:
744 {
745 if (type != LEXER_RIGHT_PAREN)
746 {
747 break;
748 }
749
750 lexer_next_token (context_p);
751
752 if (context_p->token.type != LEXER_LEFT_BRACE)
753 {
754 break;
755 }
756
757 #if ENABLED (JERRY_ES2015)
758 scanner_literal_pool_t *literal_pool_p;
759 literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_BLOCK);
760 literal_pool_p->source_p = context_p->source_p - 1;
761 #endif /* ENABLED (JERRY_ES2015) */
762
763 parser_stack_pop_uint8 (context_p);
764
765 scanner_switch_statement_t switch_statement = scanner_context_p->active_switch_statement;
766 parser_stack_push (context_p, &switch_statement, sizeof (scanner_switch_statement_t));
767 parser_stack_push_uint8 (context_p, SCAN_STACK_SWITCH_BLOCK);
768
769 scanner_switch_info_t *switch_info_p;
770 switch_info_p = (scanner_switch_info_t *) scanner_insert_info (context_p,
771 context_p->source_p,
772 sizeof (scanner_switch_info_t));
773 switch_info_p->info.type = SCANNER_TYPE_SWITCH;
774 switch_info_p->case_p = NULL;
775 scanner_context_p->active_switch_statement.last_case_p = &switch_info_p->case_p;
776
777 lexer_next_token (context_p);
778
779 if (context_p->token.type != LEXER_RIGHT_BRACE
780 && context_p->token.type != LEXER_KEYW_CASE
781 && context_p->token.type != LEXER_KEYW_DEFAULT)
782 {
783 break;
784 }
785
786 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
787 return SCAN_KEEP_TOKEN;
788 }
789 case SCAN_STACK_CASE_STATEMENT:
790 {
791 if (type != LEXER_COLON)
792 {
793 break;
794 }
795
796 scanner_source_start_t source_start;
797
798 parser_stack_pop_uint8 (context_p);
799 parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
800
801 scanner_location_info_t *location_info_p;
802 location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
803 source_start.source_p,
804 sizeof (scanner_location_info_t));
805 location_info_p->info.type = SCANNER_TYPE_CASE;
806
807 scanner_get_location (&location_info_p->location, context_p);
808
809 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
810 return SCAN_NEXT_TOKEN;
811 }
812 case SCAN_STACK_COLON_EXPRESSION:
813 {
814 if (type != LEXER_COLON)
815 {
816 break;
817 }
818
819 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
820 parser_stack_pop_uint8 (context_p);
821 return SCAN_NEXT_TOKEN;
822 }
823 #if ENABLED (JERRY_ES2015)
824 case SCAN_STACK_ARRAY_LITERAL:
825 case SCAN_STACK_OBJECT_LITERAL:
826 {
827 if (((stack_top == SCAN_STACK_ARRAY_LITERAL) && (type != LEXER_RIGHT_SQUARE))
828 || ((stack_top == SCAN_STACK_OBJECT_LITERAL) && (type != LEXER_RIGHT_BRACE)))
829 {
830 break;
831 }
832
833 scanner_source_start_t source_start;
834 uint8_t binding_type = scanner_context_p->binding_type;
835
836 parser_stack_pop_uint8 (context_p);
837 scanner_context_p->binding_type = context_p->stack_top_uint8;
838 parser_stack_pop_uint8 (context_p);
839 parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
840
841 lexer_next_token (context_p);
842
843 if (binding_type == SCANNER_BINDING_CATCH && context_p->stack_top_uint8 == SCAN_STACK_CATCH_STATEMENT)
844 {
845 scanner_pop_binding_list (scanner_context_p);
846
847 if (context_p->token.type != LEXER_RIGHT_PAREN)
848 {
849 scanner_raise_error (context_p);
850 }
851
852 lexer_next_token (context_p);
853
854 if (context_p->token.type != LEXER_LEFT_BRACE)
855 {
856 scanner_raise_error (context_p);
857 }
858
859 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
860 return SCAN_NEXT_TOKEN;
861 }
862
863 if (context_p->token.type != LEXER_ASSIGN)
864 {
865 if (SCANNER_NEEDS_BINDING_LIST (binding_type))
866 {
867 scanner_pop_binding_list (scanner_context_p);
868 }
869
870 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
871 return SCAN_KEEP_TOKEN;
872 }
873
874 scanner_location_info_t *location_info_p;
875 location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
876 source_start.source_p,
877 sizeof (scanner_location_info_t));
878 location_info_p->info.type = SCANNER_TYPE_INITIALIZER;
879 scanner_get_location (&location_info_p->location, context_p);
880 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
881
882 if (SCANNER_NEEDS_BINDING_LIST (binding_type))
883 {
884 scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p;
885
886 while (item_p != NULL)
887 {
888 item_p->literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_USED;
889 item_p = item_p->next_p;
890 }
891
892 parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_LIST_INIT);
893 }
894 return SCAN_NEXT_TOKEN;
895 }
896 #else /* !ENABLED (JERRY_ES2015) */
897 case SCAN_STACK_ARRAY_LITERAL:
898 #endif /* ENABLED (JERRY_ES2015) */
899 case SCAN_STACK_PROPERTY_ACCESSOR:
900 {
901 if (type != LEXER_RIGHT_SQUARE)
902 {
903 break;
904 }
905
906 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
907 parser_stack_pop_uint8 (context_p);
908 return SCAN_NEXT_TOKEN;
909 }
910 #if !ENABLED (JERRY_ES2015)
911 case SCAN_STACK_OBJECT_LITERAL:
912 {
913 if (type != LEXER_RIGHT_BRACE)
914 {
915 break;
916 }
917
918 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
919 parser_stack_pop_uint8 (context_p);
920 return SCAN_NEXT_TOKEN;
921 }
922 #endif /* !ENABLED (JERRY_ES2015) */
923 #if ENABLED (JERRY_ES2015)
924 case SCAN_STACK_COMPUTED_PROPERTY:
925 {
926 if (type != LEXER_RIGHT_SQUARE)
927 {
928 break;
929 }
930
931 lexer_next_token (context_p);
932
933 parser_stack_pop_uint8 (context_p);
934 stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
935
936 if (stack_top == SCAN_STACK_FUNCTION_PROPERTY)
937 {
938 scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
939
940 scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
941 return SCAN_KEEP_TOKEN;
942 }
943
944 JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL);
945
946 if (context_p->token.type == LEXER_LEFT_PAREN)
947 {
948 scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
949
950 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
951 scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
952 return SCAN_KEEP_TOKEN;
953 }
954
955 if (context_p->token.type != LEXER_COLON)
956 {
957 scanner_raise_error (context_p);
958 }
959
960 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
961
962 if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
963 {
964 scanner_context_p->mode = SCAN_MODE_BINDING;
965 }
966 return SCAN_NEXT_TOKEN;
967 }
968 case SCAN_STACK_COMPUTED_GENERATOR:
969 case SCAN_STACK_COMPUTED_ASYNC:
970 case SCAN_STACK_COMPUTED_ASYNC_GENERATOR:
971 {
972 if (type != LEXER_RIGHT_SQUARE)
973 {
974 break;
975 }
976
977 lexer_next_token (context_p);
978 parser_stack_pop_uint8 (context_p);
979
980 JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
981 || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PROPERTY);
982
983 uint16_t status_flags = (uint16_t) (SCANNER_LITERAL_POOL_FUNCTION
984 | SCANNER_LITERAL_POOL_GENERATOR
985 | SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (stack_top));
986
987 scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
988
989 scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
990 return SCAN_KEEP_TOKEN;
991 }
992 case SCAN_STACK_TEMPLATE_STRING:
993 case SCAN_STACK_TAGGED_TEMPLATE_LITERAL:
994 {
995 if (type != LEXER_RIGHT_BRACE)
996 {
997 break;
998 }
999
1000 context_p->source_p--;
1001 context_p->column--;
1002 lexer_parse_string (context_p, LEXER_STRING_NO_OPTS);
1003
1004 if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
1005 {
1006 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1007 }
1008 else
1009 {
1010 parser_stack_pop_uint8 (context_p);
1011 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1012 }
1013 return SCAN_NEXT_TOKEN;
1014 }
1015 case SCAN_STACK_ARROW_ARGUMENTS:
1016 {
1017 if (type != LEXER_RIGHT_PAREN)
1018 {
1019 break;
1020 }
1021
1022 scanner_check_arrow (context_p, scanner_context_p);
1023 return SCAN_KEEP_TOKEN;
1024 }
1025 case SCAN_STACK_ARROW_EXPRESSION:
1026 {
1027 scanner_pop_literal_pool (context_p, scanner_context_p);
1028 parser_stack_pop_uint8 (context_p);
1029 lexer_update_await_yield (context_p, context_p->status_flags);
1030 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
1031 return SCAN_KEEP_TOKEN;
1032 }
1033 case SCAN_STACK_CLASS_EXTENDS:
1034 {
1035 if (type != LEXER_LEFT_BRACE)
1036 {
1037 break;
1038 }
1039
1040 scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
1041 parser_stack_pop_uint8 (context_p);
1042
1043 return SCAN_KEEP_TOKEN;
1044 }
1045 case SCAN_STACK_FUNCTION_PARAMETERS:
1046 {
1047 parser_stack_pop_uint8 (context_p);
1048
1049 if (type != LEXER_RIGHT_PAREN
1050 && (type != LEXER_EOS || context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION))
1051 {
1052 break;
1053 }
1054
1055 scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
1056 return SCAN_KEEP_TOKEN;
1057 }
1058 #endif /* ENABLED (JERRY_ES2015) */
1059 default:
1060 {
1061 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1062 return SCAN_KEEP_TOKEN;
1063 }
1064 }
1065
1066 scanner_raise_error (context_p);
1067 return SCAN_NEXT_TOKEN;
1068 } /* scanner_scan_primary_expression_end */
1069
1070 /**
1071 * Scan statements.
1072 *
1073 * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
1074 */
1075 static scan_return_types_t
scanner_scan_statement(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_token_type_t type,scan_stack_modes_t stack_top)1076 scanner_scan_statement (parser_context_t *context_p, /**< context */
1077 scanner_context_t *scanner_context_p, /**< scanner context */
1078 lexer_token_type_t type, /**< current token type */
1079 scan_stack_modes_t stack_top) /**< current stack top */
1080 {
1081 switch (type)
1082 {
1083 case LEXER_SEMICOLON:
1084 {
1085 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1086 return SCAN_KEEP_TOKEN;
1087 }
1088 case LEXER_LEFT_BRACE:
1089 {
1090 #if ENABLED (JERRY_ES2015)
1091 scanner_literal_pool_t *literal_pool_p;
1092 literal_pool_p = scanner_push_literal_pool (context_p,
1093 scanner_context_p,
1094 SCANNER_LITERAL_POOL_BLOCK);
1095 literal_pool_p->source_p = context_p->source_p;
1096 #endif /* ENABLED (JERRY_ES2015) */
1097
1098 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
1099 parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
1100 return SCAN_NEXT_TOKEN;
1101 }
1102 case LEXER_KEYW_DO:
1103 {
1104 scanner_context_p->mode = SCAN_MODE_STATEMENT;
1105 parser_stack_push_uint8 (context_p, SCAN_STACK_DO_STATEMENT);
1106 return SCAN_NEXT_TOKEN;
1107 }
1108 case LEXER_KEYW_TRY:
1109 {
1110 lexer_next_token (context_p);
1111
1112 if (context_p->token.type != LEXER_LEFT_BRACE)
1113 {
1114 scanner_raise_error (context_p);
1115 }
1116
1117 #if ENABLED (JERRY_ES2015)
1118 scanner_literal_pool_t *literal_pool_p;
1119 literal_pool_p = scanner_push_literal_pool (context_p,
1120 scanner_context_p,
1121 SCANNER_LITERAL_POOL_BLOCK);
1122 literal_pool_p->source_p = context_p->source_p;
1123 #endif /* ENABLED (JERRY_ES2015) */
1124
1125 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
1126 parser_stack_push_uint8 (context_p, SCAN_STACK_TRY_STATEMENT);
1127 return SCAN_NEXT_TOKEN;
1128 }
1129 case LEXER_KEYW_DEBUGGER:
1130 {
1131 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1132 return SCAN_NEXT_TOKEN;
1133 }
1134 case LEXER_KEYW_IF:
1135 case LEXER_KEYW_WITH:
1136 case LEXER_KEYW_SWITCH:
1137 {
1138 lexer_next_token (context_p);
1139 if (context_p->token.type != LEXER_LEFT_PAREN)
1140 {
1141 scanner_raise_error (context_p);
1142 }
1143
1144 uint8_t mode = SCAN_STACK_STATEMENT_WITH_EXPR;
1145
1146 if (type == LEXER_KEYW_IF)
1147 {
1148 parser_stack_push_uint8 (context_p, SCAN_STACK_IF_STATEMENT);
1149 }
1150 else if (type == LEXER_KEYW_WITH)
1151 {
1152 mode = SCAN_STACK_WITH_EXPRESSION;
1153 }
1154 else if (type == LEXER_KEYW_SWITCH)
1155 {
1156 mode = SCAN_STACK_SWITCH_EXPRESSION;
1157 }
1158
1159 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1160 parser_stack_push_uint8 (context_p, mode);
1161 return SCAN_NEXT_TOKEN;
1162 }
1163 case LEXER_KEYW_WHILE:
1164 {
1165 lexer_next_token (context_p);
1166
1167 if (context_p->token.type != LEXER_LEFT_PAREN)
1168 {
1169 scanner_raise_error (context_p);
1170 }
1171
1172 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1173
1174 scanner_source_start_t source_start;
1175 source_start.source_p = context_p->source_p;
1176
1177 parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1178 parser_stack_push_uint8 (context_p, SCAN_STACK_WHILE_EXPRESSION);
1179 return SCAN_NEXT_TOKEN;
1180 }
1181 case LEXER_KEYW_FOR:
1182 {
1183 lexer_next_token (context_p);
1184 if (context_p->token.type != LEXER_LEFT_PAREN)
1185 {
1186 scanner_raise_error (context_p);
1187 }
1188
1189 scanner_for_statement_t for_statement;
1190 for_statement.u.source_p = context_p->source_p;
1191 uint8_t stack_mode = SCAN_STACK_FOR_START;
1192 scan_return_types_t return_type = SCAN_KEEP_TOKEN;
1193
1194 lexer_next_token (context_p);
1195 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1196
1197 #if ENABLED (JERRY_ES2015)
1198 const uint8_t *source_p = context_p->source_p;
1199 #endif /* ENABLED (JERRY_ES2015) */
1200
1201 switch (context_p->token.type)
1202 {
1203 case LEXER_SEMICOLON:
1204 {
1205 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
1206 break;
1207 }
1208 case LEXER_KEYW_VAR:
1209 {
1210 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1211 stack_mode = SCAN_STACK_FOR_VAR_START;
1212 return_type = SCAN_NEXT_TOKEN;
1213 break;
1214 }
1215 #if ENABLED (JERRY_ES2015)
1216 case LEXER_LITERAL:
1217 {
1218 if (!lexer_token_is_let (context_p))
1219 {
1220 break;
1221 }
1222
1223 parser_line_counter_t line = context_p->line;
1224 parser_line_counter_t column = context_p->column;
1225
1226 if (lexer_check_arrow (context_p))
1227 {
1228 context_p->source_p = source_p;
1229 context_p->line = line;
1230 context_p->column = column;
1231 context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES;
1232 break;
1233 }
1234
1235 lexer_next_token (context_p);
1236
1237 type = (lexer_token_type_t) context_p->token.type;
1238
1239 if (type != LEXER_LEFT_SQUARE
1240 && type != LEXER_LEFT_BRACE
1241 && (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL))
1242 {
1243 scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t));
1244 info_p->type = SCANNER_TYPE_LET_EXPRESSION;
1245
1246 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1247 break;
1248 }
1249
1250 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1251 /* FALLTHRU */
1252 }
1253 case LEXER_KEYW_LET:
1254 case LEXER_KEYW_CONST:
1255 {
1256 scanner_literal_pool_t *literal_pool_p;
1257 literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_BLOCK);
1258 literal_pool_p->source_p = source_p;
1259
1260 if (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION)
1261 {
1262 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1263 return_type = SCAN_NEXT_TOKEN;
1264 }
1265
1266 stack_mode = ((context_p->token.type == LEXER_KEYW_CONST) ? SCAN_STACK_FOR_CONST_START
1267 : SCAN_STACK_FOR_LET_START);
1268 break;
1269 }
1270 #endif /* ENABLED (JERRY_ES2015) */
1271 }
1272
1273 parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t));
1274 parser_stack_push_uint8 (context_p, stack_mode);
1275 return return_type;
1276 }
1277 case LEXER_KEYW_VAR:
1278 {
1279 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1280 parser_stack_push_uint8 (context_p, SCAN_STACK_VAR);
1281 return SCAN_NEXT_TOKEN;
1282 }
1283 #if ENABLED (JERRY_ES2015)
1284 case LEXER_KEYW_LET:
1285 {
1286 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1287 parser_stack_push_uint8 (context_p, SCAN_STACK_LET);
1288 return SCAN_NEXT_TOKEN;
1289 }
1290 case LEXER_KEYW_CONST:
1291 {
1292 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1293 parser_stack_push_uint8 (context_p, SCAN_STACK_CONST);
1294 return SCAN_NEXT_TOKEN;
1295 }
1296 #endif /* ENABLED (JERRY_ES2015) */
1297 case LEXER_KEYW_THROW:
1298 {
1299 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1300 return SCAN_NEXT_TOKEN;
1301 }
1302 case LEXER_KEYW_RETURN:
1303 {
1304 lexer_next_token (context_p);
1305
1306 if (!(context_p->token.flags & LEXER_WAS_NEWLINE)
1307 && context_p->token.type != LEXER_SEMICOLON
1308 && context_p->token.type != LEXER_EOS
1309 && context_p->token.type != LEXER_RIGHT_BRACE)
1310 {
1311 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1312 return SCAN_KEEP_TOKEN;
1313 }
1314
1315 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1316 return SCAN_KEEP_TOKEN;
1317 }
1318 case LEXER_KEYW_BREAK:
1319 case LEXER_KEYW_CONTINUE:
1320 {
1321 lexer_next_token (context_p);
1322 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1323
1324 if (!(context_p->token.flags & LEXER_WAS_NEWLINE)
1325 && context_p->token.type == LEXER_LITERAL
1326 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1327 {
1328 return SCAN_NEXT_TOKEN;
1329 }
1330 return SCAN_KEEP_TOKEN;
1331 }
1332 case LEXER_KEYW_CASE:
1333 case LEXER_KEYW_DEFAULT:
1334 {
1335 if (stack_top != SCAN_STACK_SWITCH_BLOCK)
1336 {
1337 scanner_raise_error (context_p);
1338 }
1339
1340 scanner_case_info_t *case_info_p;
1341 case_info_p = (scanner_case_info_t *) scanner_malloc (context_p, sizeof (scanner_case_info_t));
1342
1343 *(scanner_context_p->active_switch_statement.last_case_p) = case_info_p;
1344 scanner_context_p->active_switch_statement.last_case_p = &case_info_p->next_p;
1345
1346 case_info_p->next_p = NULL;
1347 scanner_get_location (&case_info_p->location, context_p);
1348
1349 if (type == LEXER_KEYW_DEFAULT)
1350 {
1351 lexer_next_token (context_p);
1352
1353 if (context_p->token.type != LEXER_COLON)
1354 {
1355 scanner_raise_error (context_p);
1356 }
1357
1358 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
1359 return SCAN_NEXT_TOKEN;
1360 }
1361
1362 scanner_source_start_t source_start;
1363 source_start.source_p = context_p->source_p;
1364
1365 parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1366 parser_stack_push_uint8 (context_p, SCAN_STACK_CASE_STATEMENT);
1367
1368 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1369 return SCAN_NEXT_TOKEN;
1370 }
1371 case LEXER_KEYW_FUNCTION:
1372 {
1373 #if ENABLED (JERRY_ES2015)
1374 uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_FUNCTION_STATEMENT;
1375
1376 if (scanner_context_p->async_source_p != NULL)
1377 {
1378 scanner_context_p->status_flags |= SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION;
1379 status_flags |= SCANNER_LITERAL_POOL_ASYNC;
1380 }
1381 #endif /* ENABLED (JERRY_ES2015) */
1382
1383 lexer_next_token (context_p);
1384
1385 #if ENABLED (JERRY_ES2015)
1386 if (context_p->token.type == LEXER_MULTIPLY)
1387 {
1388 status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
1389 lexer_next_token (context_p);
1390 }
1391 #endif /* ENABLED (JERRY_ES2015) */
1392
1393 if (context_p->token.type != LEXER_LITERAL
1394 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1395 {
1396 scanner_raise_error (context_p);
1397 }
1398
1399 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
1400
1401 #if ENABLED (JERRY_ES2015)
1402 const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL);
1403
1404 if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL)
1405 && (literal_p->type & mask) != (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
1406 && (literal_p->type & mask) != (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION))
1407 {
1408 scanner_raise_redeclaration_error (context_p);
1409 }
1410
1411 literal_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION;
1412
1413 scanner_context_p->status_flags &= (uint16_t) ~SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION;
1414 #else
1415 literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
1416
1417 uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
1418 #endif /* ENABLED (JERRY_ES2015) */
1419
1420 scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
1421
1422 scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
1423 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
1424 return SCAN_NEXT_TOKEN;
1425 }
1426 #if ENABLED (JERRY_ES2015)
1427 case LEXER_KEYW_CLASS:
1428 {
1429 scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_STATEMENT);
1430
1431 if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1432 {
1433 scanner_raise_error (context_p);
1434 }
1435
1436 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
1437
1438 scanner_detect_invalid_let (context_p, literal_p);
1439 literal_p->type |= SCANNER_LITERAL_IS_LET;
1440
1441 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1442 if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT)
1443 {
1444 literal_p->type |= SCANNER_LITERAL_NO_REG;
1445 scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
1446 }
1447 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1448
1449 return SCAN_NEXT_TOKEN;
1450 }
1451 #endif /* ENABLED (JERRY_ES2015) */
1452 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1453 case LEXER_KEYW_IMPORT:
1454 {
1455 if (stack_top != SCAN_STACK_SCRIPT)
1456 {
1457 scanner_raise_error (context_p);
1458 }
1459
1460 context_p->global_status_flags |= ECMA_PARSE_MODULE;
1461
1462 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1463 lexer_next_token (context_p);
1464
1465 if (context_p->token.type == LEXER_LITERAL
1466 && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
1467 {
1468 return SCAN_NEXT_TOKEN;
1469 }
1470
1471 bool parse_imports = true;
1472
1473 if (context_p->token.type == LEXER_LITERAL
1474 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1475 {
1476 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
1477
1478 #if ENABLED (JERRY_ES2015)
1479 scanner_detect_invalid_let (context_p, literal_p);
1480 literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG;
1481 #else /* !ENABLED (JERRY_ES2015) */
1482 literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_NO_REG;
1483 #endif /* ENABLED (JERRY_ES2015) */
1484
1485 lexer_next_token (context_p);
1486
1487 if (context_p->token.type == LEXER_COMMA)
1488 {
1489 lexer_next_token (context_p);
1490 }
1491 else
1492 {
1493 parse_imports = false;
1494 }
1495 }
1496
1497 if (parse_imports)
1498 {
1499 if (context_p->token.type == LEXER_MULTIPLY)
1500 {
1501 lexer_next_token (context_p);
1502 if (!lexer_token_is_identifier (context_p, "as", 2))
1503 {
1504 scanner_raise_error (context_p);
1505 }
1506
1507 lexer_next_token (context_p);
1508
1509 if (context_p->token.type != LEXER_LITERAL
1510 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1511 {
1512 scanner_raise_error (context_p);
1513 }
1514
1515 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
1516
1517 #if ENABLED (JERRY_ES2015)
1518 scanner_detect_invalid_let (context_p, literal_p);
1519 literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG;
1520 #else /* !ENABLED (JERRY_ES2015) */
1521 literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_NO_REG;
1522 #endif /* ENABLED (JERRY_ES2015) */
1523
1524 lexer_next_token (context_p);
1525 }
1526 else if (context_p->token.type == LEXER_LEFT_BRACE)
1527 {
1528 lexer_next_token (context_p);
1529
1530 while (context_p->token.type != LEXER_RIGHT_BRACE)
1531 {
1532 if (context_p->token.type != LEXER_LITERAL
1533 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1534 {
1535 scanner_raise_error (context_p);
1536 }
1537
1538 #if ENABLED (JERRY_ES2015)
1539 const uint8_t *source_p = context_p->source_p;
1540 #endif /* ENABLED (JERRY_ES2015) */
1541
1542 if (lexer_check_next_character (context_p, LIT_CHAR_LOWERCASE_A))
1543 {
1544 lexer_next_token (context_p);
1545
1546 if (!lexer_token_is_identifier (context_p, "as", 2))
1547 {
1548 scanner_raise_error (context_p);
1549 }
1550
1551 lexer_next_token (context_p);
1552
1553 if (context_p->token.type != LEXER_LITERAL
1554 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1555 {
1556 scanner_raise_error (context_p);
1557 }
1558
1559 #if ENABLED (JERRY_ES2015)
1560 source_p = context_p->source_p;
1561 #endif /* ENABLED (JERRY_ES2015) */
1562 }
1563
1564 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
1565
1566 #if ENABLED (JERRY_ES2015)
1567 if (literal_p->type & (SCANNER_LITERAL_IS_ARG
1568 | SCANNER_LITERAL_IS_VAR
1569 | SCANNER_LITERAL_IS_LOCAL))
1570 {
1571 context_p->source_p = source_p;
1572 scanner_raise_redeclaration_error (context_p);
1573 }
1574
1575 if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
1576 {
1577 literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
1578 }
1579
1580 literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG;
1581 #else /* !ENABLED (JERRY_ES2015) */
1582 literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_NO_REG;
1583 #endif /* ENABLED (JERRY_ES2015) */
1584
1585 lexer_next_token (context_p);
1586
1587 if (context_p->token.type != LEXER_RIGHT_BRACE)
1588 {
1589 if (context_p->token.type != LEXER_COMMA)
1590 {
1591 scanner_raise_error (context_p);
1592 }
1593
1594 lexer_next_token (context_p);
1595 }
1596 }
1597
1598 lexer_next_token (context_p);
1599 }
1600 else
1601 {
1602 scanner_raise_error (context_p);
1603 }
1604 }
1605
1606 if (!lexer_token_is_identifier (context_p, "from", 4))
1607 {
1608 scanner_raise_error (context_p);
1609 }
1610
1611 lexer_next_token (context_p);
1612
1613 if (context_p->token.type != LEXER_LITERAL
1614 && context_p->token.lit_location.type != LEXER_STRING_LITERAL)
1615 {
1616 scanner_raise_error (context_p);
1617 }
1618
1619 return SCAN_NEXT_TOKEN;
1620 }
1621 case LEXER_KEYW_EXPORT:
1622 {
1623 if (stack_top != SCAN_STACK_SCRIPT)
1624 {
1625 scanner_raise_error (context_p);
1626 }
1627
1628 context_p->global_status_flags |= ECMA_PARSE_MODULE;
1629
1630 lexer_next_token (context_p);
1631
1632 if (context_p->token.type == LEXER_KEYW_DEFAULT)
1633 {
1634 lexer_next_token (context_p);
1635
1636 if (context_p->token.type == LEXER_KEYW_FUNCTION)
1637 {
1638 lexer_next_token (context_p);
1639 if (context_p->token.type == LEXER_LITERAL
1640 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1641 {
1642 lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
1643
1644 #if ENABLED (JERRY_ES2015)
1645 if (location_p->type & SCANNER_LITERAL_IS_LOCAL
1646 && !(location_p->type & SCANNER_LITERAL_IS_FUNC))
1647 {
1648 scanner_raise_redeclaration_error (context_p);
1649 }
1650 location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
1651 #else /* !ENABLED (JERRY_ES2015) */
1652 location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
1653 #endif /* ENABLED (JERRY_ES2015) */
1654
1655 lexer_next_token (context_p);
1656 }
1657 else
1658 {
1659 lexer_lit_location_t *location_p;
1660 location_p = scanner_add_custom_literal (context_p,
1661 scanner_context_p->active_literal_pool_p,
1662 &lexer_default_literal);
1663 #if ENABLED (JERRY_ES2015)
1664 location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
1665 #else /* !ENABLED (JERRY_ES2015) */
1666 location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
1667 #endif /* ENABLED (JERRY_ES2015) */
1668 }
1669
1670 scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
1671
1672 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
1673 scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
1674 return SCAN_KEEP_TOKEN;
1675 }
1676 #if ENABLED (JERRY_ES2015)
1677 if (context_p->token.type == LEXER_KEYW_CLASS)
1678 {
1679 scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_STATEMENT);
1680
1681 if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1682 {
1683 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
1684
1685 scanner_detect_invalid_let (context_p, literal_p);
1686
1687 literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
1688 return SCAN_NEXT_TOKEN;
1689 }
1690
1691 lexer_lit_location_t *literal_p;
1692 literal_p = scanner_add_custom_literal (context_p,
1693 scanner_context_p->active_literal_pool_p,
1694 &lexer_default_literal);
1695 literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
1696 return SCAN_KEEP_TOKEN;
1697 }
1698 #endif /* ENABLED (JERRY_ES2015) */
1699
1700 /* Assignment expression. */
1701 lexer_lit_location_t *location_p;
1702 location_p = scanner_add_custom_literal (context_p,
1703 scanner_context_p->active_literal_pool_p,
1704 &lexer_default_literal);
1705 location_p->type |= SCANNER_LITERAL_IS_VAR;
1706 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1707
1708 if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1709 {
1710 return SCAN_KEEP_TOKEN;
1711 }
1712
1713 location_p = scanner_add_literal (context_p, scanner_context_p);
1714 location_p->type |= SCANNER_LITERAL_IS_VAR;
1715 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1716 return SCAN_NEXT_TOKEN;
1717 }
1718
1719 scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
1720
1721 if (context_p->token.type == LEXER_MULTIPLY)
1722 {
1723 lexer_next_token (context_p);
1724 if (!lexer_token_is_identifier (context_p, "from", 4))
1725 {
1726 scanner_raise_error (context_p);
1727 }
1728
1729 lexer_next_token (context_p);
1730
1731 if (context_p->token.type != LEXER_LITERAL
1732 && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
1733 {
1734 scanner_raise_error (context_p);
1735 }
1736
1737 return SCAN_NEXT_TOKEN;
1738 }
1739
1740 if (context_p->token.type == LEXER_LEFT_BRACE)
1741 {
1742 lexer_next_token (context_p);
1743
1744 while (context_p->token.type != LEXER_RIGHT_BRACE)
1745 {
1746 if (context_p->token.type != LEXER_LITERAL
1747 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1748 {
1749 scanner_raise_error (context_p);
1750 }
1751
1752 lexer_next_token (context_p);
1753
1754 if (lexer_token_is_identifier (context_p, "as", 2))
1755 {
1756 lexer_next_token (context_p);
1757
1758 if (context_p->token.type != LEXER_LITERAL
1759 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1760 {
1761 scanner_raise_error (context_p);
1762 }
1763
1764 lexer_next_token (context_p);
1765 }
1766
1767 if (context_p->token.type != LEXER_RIGHT_BRACE)
1768 {
1769 if (context_p->token.type != LEXER_COMMA)
1770 {
1771 scanner_raise_error (context_p);
1772 }
1773
1774 lexer_next_token (context_p);
1775 }
1776 }
1777
1778 lexer_next_token (context_p);
1779
1780 if (!lexer_token_is_identifier (context_p, "from", 4))
1781 {
1782 return SCAN_KEEP_TOKEN;
1783 }
1784
1785 lexer_next_token (context_p);
1786
1787 if (context_p->token.type != LEXER_LITERAL
1788 && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
1789 {
1790 scanner_raise_error (context_p);
1791 }
1792
1793 return SCAN_NEXT_TOKEN;
1794 }
1795
1796 switch (context_p->token.type)
1797 {
1798 #if ENABLED (JERRY_ES2015)
1799 case LEXER_KEYW_CLASS:
1800 case LEXER_KEYW_LET:
1801 case LEXER_KEYW_CONST:
1802 #endif /* ENABLED (JERRY_ES2015) */
1803 case LEXER_KEYW_VAR:
1804 {
1805 scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IN_EXPORT;
1806 break;
1807 }
1808 }
1809
1810 scanner_context_p->mode = SCAN_MODE_STATEMENT;
1811 return SCAN_KEEP_TOKEN;
1812 }
1813 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1814 default:
1815 {
1816 break;
1817 }
1818 }
1819
1820 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
1821
1822 if (type == LEXER_LITERAL
1823 && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
1824 {
1825 if (JERRY_UNLIKELY (lexer_check_next_character (context_p, LIT_CHAR_COLON)))
1826 {
1827 lexer_consume_next_character (context_p);
1828 scanner_context_p->mode = SCAN_MODE_STATEMENT;
1829 return SCAN_NEXT_TOKEN;
1830 }
1831
1832 JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES);
1833
1834 #if ENABLED (JERRY_ES2015)
1835 /* The colon needs to be checked first because the parser also checks
1836 * it first, and this check skips the spaces which affects source_p. */
1837 if (JERRY_UNLIKELY (lexer_check_arrow (context_p)))
1838 {
1839 scanner_scan_simple_arrow (context_p, scanner_context_p, context_p->source_p);
1840 return SCAN_KEEP_TOKEN;
1841 }
1842
1843 if (JERRY_UNLIKELY (lexer_token_is_let (context_p)))
1844 {
1845 lexer_lit_location_t let_literal = context_p->token.lit_location;
1846 const uint8_t *source_p = context_p->source_p;
1847
1848 lexer_next_token (context_p);
1849
1850 type = (lexer_token_type_t) context_p->token.type;
1851
1852 if (type == LEXER_LEFT_SQUARE
1853 || type == LEXER_LEFT_BRACE
1854 || (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL))
1855 {
1856 scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
1857 parser_stack_push_uint8 (context_p, SCAN_STACK_LET);
1858 return SCAN_KEEP_TOKEN;
1859 }
1860
1861 scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t));
1862 info_p->type = SCANNER_TYPE_LET_EXPRESSION;
1863
1864 lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
1865 scanner_context_p->active_literal_pool_p,
1866 &let_literal);
1867 lit_location_p->type |= SCANNER_LITERAL_IS_USED;
1868
1869 if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
1870 {
1871 lit_location_p->type |= SCANNER_LITERAL_NO_REG;
1872 }
1873
1874 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1875 return SCAN_KEEP_TOKEN;
1876 }
1877
1878 if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
1879 {
1880 scanner_context_p->async_source_p = context_p->source_p;
1881
1882 if (scanner_check_async_function (context_p, scanner_context_p))
1883 {
1884 scanner_context_p->mode = SCAN_MODE_STATEMENT;
1885 }
1886 return SCAN_KEEP_TOKEN;
1887 }
1888 #endif /* ENABLED (JERRY_ES2015) */
1889
1890 scanner_add_reference (context_p, scanner_context_p);
1891
1892 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1893 return SCAN_NEXT_TOKEN;
1894 }
1895
1896 return SCAN_KEEP_TOKEN;
1897 } /* scanner_scan_statement */
1898
1899 /**
1900 * Scan statement terminator.
1901 *
1902 * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
1903 */
1904 static scan_return_types_t
scanner_scan_statement_end(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_token_type_t type)1905 scanner_scan_statement_end (parser_context_t *context_p, /**< context */
1906 scanner_context_t *scanner_context_p, /**< scanner context */
1907 lexer_token_type_t type) /**< current token type */
1908 {
1909 bool terminator_found = false;
1910
1911 if (type == LEXER_SEMICOLON)
1912 {
1913 lexer_next_token (context_p);
1914 terminator_found = true;
1915 }
1916
1917 while (true)
1918 {
1919 type = (lexer_token_type_t) context_p->token.type;
1920
1921 switch (context_p->stack_top_uint8)
1922 {
1923 case SCAN_STACK_SCRIPT:
1924 case SCAN_STACK_SCRIPT_FUNCTION:
1925 {
1926 if (type == LEXER_EOS)
1927 {
1928 return SCAN_NEXT_TOKEN;
1929 }
1930 break;
1931 }
1932 case SCAN_STACK_BLOCK_STATEMENT:
1933 #if ENABLED (JERRY_ES2015)
1934 case SCAN_STACK_CLASS_STATEMENT:
1935 #endif /* ENABLED (JERRY_ES2015) */
1936 case SCAN_STACK_FUNCTION_STATEMENT:
1937 {
1938 if (type != LEXER_RIGHT_BRACE)
1939 {
1940 break;
1941 }
1942
1943 #if ENABLED (JERRY_ES2015)
1944 if (context_p->stack_top_uint8 != SCAN_STACK_CLASS_STATEMENT)
1945 {
1946 scanner_pop_literal_pool (context_p, scanner_context_p);
1947 }
1948 #else /* !ENABLED (JERRY_ES2015) */
1949 if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_STATEMENT)
1950 {
1951 scanner_pop_literal_pool (context_p, scanner_context_p);
1952 }
1953 #endif /* ENABLED (JERRY_ES2015) */
1954
1955 terminator_found = true;
1956 parser_stack_pop_uint8 (context_p);
1957 lexer_next_token (context_p);
1958 continue;
1959 }
1960 case SCAN_STACK_FUNCTION_EXPRESSION:
1961 #if ENABLED (JERRY_ES2015)
1962 case SCAN_STACK_FUNCTION_ARROW:
1963 #endif /* ENABLED (JERRY_ES2015) */
1964 {
1965 if (type != LEXER_RIGHT_BRACE)
1966 {
1967 break;
1968 }
1969
1970 scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1971 #if ENABLED (JERRY_ES2015)
1972 if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_ARROW)
1973 {
1974 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
1975 }
1976 #endif /* ENABLED (JERRY_ES2015) */
1977
1978 scanner_pop_literal_pool (context_p, scanner_context_p);
1979 parser_stack_pop_uint8 (context_p);
1980 return SCAN_NEXT_TOKEN;
1981 }
1982 case SCAN_STACK_FUNCTION_PROPERTY:
1983 {
1984 if (type != LEXER_RIGHT_BRACE)
1985 {
1986 break;
1987 }
1988
1989 scanner_pop_literal_pool (context_p, scanner_context_p);
1990 parser_stack_pop_uint8 (context_p);
1991
1992 #if ENABLED (JERRY_ES2015)
1993 if (context_p->stack_top_uint8 == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR
1994 || context_p->stack_top_uint8 == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
1995 {
1996 scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
1997 return SCAN_KEEP_TOKEN;
1998 }
1999 #endif /* ENABLED (JERRY_ES2015) */
2000
2001 JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL);
2002
2003 lexer_next_token (context_p);
2004
2005 if (context_p->token.type == LEXER_RIGHT_BRACE)
2006 {
2007 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
2008 return SCAN_KEEP_TOKEN;
2009 }
2010
2011 if (context_p->token.type != LEXER_COMMA)
2012 {
2013 scanner_raise_error (context_p);
2014 }
2015
2016 scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
2017 return SCAN_KEEP_TOKEN;
2018 }
2019 case SCAN_STACK_SWITCH_BLOCK:
2020 {
2021 if (type != LEXER_RIGHT_BRACE)
2022 {
2023 break;
2024 }
2025
2026 scanner_switch_statement_t switch_statement;
2027
2028 parser_stack_pop_uint8 (context_p);
2029 parser_stack_pop (context_p, &switch_statement, sizeof (scanner_switch_statement_t));
2030
2031 scanner_context_p->active_switch_statement = switch_statement;
2032
2033 #if ENABLED (JERRY_ES2015)
2034 scanner_pop_literal_pool (context_p, scanner_context_p);
2035 #endif /* ENABLED (JERRY_ES2015) */
2036
2037 terminator_found = true;
2038 lexer_next_token (context_p);
2039 continue;
2040 }
2041 case SCAN_STACK_IF_STATEMENT:
2042 {
2043 parser_stack_pop_uint8 (context_p);
2044
2045 if (type == LEXER_KEYW_ELSE
2046 && (terminator_found || (context_p->token.flags & LEXER_WAS_NEWLINE)))
2047 {
2048 #if ENABLED (JERRY_ES2015)
2049 scanner_check_function_after_if (context_p, scanner_context_p);
2050 return SCAN_KEEP_TOKEN;
2051 #else /* !ENABLED (JERRY_ES2015) */
2052 scanner_context_p->mode = SCAN_MODE_STATEMENT;
2053 return SCAN_NEXT_TOKEN;
2054 #endif /* ENABLED (JERRY_ES2015) */
2055 }
2056 continue;
2057 }
2058 case SCAN_STACK_WITH_STATEMENT:
2059 {
2060 scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
2061
2062 JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH);
2063
2064 parser_stack_pop_uint8 (context_p);
2065
2066 if (context_p->stack_top_uint8 == 0)
2067 {
2068 literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_WITH;
2069 }
2070
2071 parser_stack_pop_uint8 (context_p);
2072 continue;
2073 }
2074 case SCAN_STACK_DO_STATEMENT:
2075 {
2076 parser_stack_pop_uint8 (context_p);
2077
2078 if (type != LEXER_KEYW_WHILE
2079 || (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE)))
2080 {
2081 scanner_raise_error (context_p);
2082 }
2083
2084 lexer_next_token (context_p);
2085 if (context_p->token.type != LEXER_LEFT_PAREN)
2086 {
2087 scanner_raise_error (context_p);
2088 }
2089
2090 parser_stack_push_uint8 (context_p, SCAN_STACK_DO_EXPRESSION);
2091 scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
2092 return SCAN_NEXT_TOKEN;
2093 }
2094 case SCAN_STACK_DO_EXPRESSION:
2095 {
2096 parser_stack_pop_uint8 (context_p);
2097 terminator_found = true;
2098 continue;
2099 }
2100 #if ENABLED (JERRY_ES2015)
2101 case SCAN_STACK_PRIVATE_BLOCK_EARLY:
2102 {
2103 parser_list_iterator_t literal_iterator;
2104 lexer_lit_location_t *literal_p;
2105
2106 parser_list_iterator_init (&scanner_context_p->active_literal_pool_p->literal_pool, &literal_iterator);
2107
2108 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
2109 {
2110 if ((literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST))
2111 && (literal_p->type & SCANNER_LITERAL_IS_USED))
2112 {
2113 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
2114 }
2115 }
2116 /* FALLTHRU */
2117 }
2118 case SCAN_STACK_PRIVATE_BLOCK:
2119 {
2120 parser_stack_pop_uint8 (context_p);
2121 scanner_pop_literal_pool (context_p, scanner_context_p);
2122 continue;
2123 }
2124 #endif /* ENABLED (JERRY_ES2015) */
2125 default:
2126 {
2127 JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_TRY_STATEMENT
2128 || context_p->stack_top_uint8 == SCAN_STACK_CATCH_STATEMENT);
2129
2130 if (type != LEXER_RIGHT_BRACE)
2131 {
2132 break;
2133 }
2134
2135 uint8_t stack_top = context_p->stack_top_uint8;
2136 parser_stack_pop_uint8 (context_p);
2137 lexer_next_token (context_p);
2138
2139 #if ENABLED (JERRY_ES2015)
2140 scanner_pop_literal_pool (context_p, scanner_context_p);
2141 #else /* !ENABLED (JERRY_ES2015) */
2142 if (stack_top == SCAN_STACK_CATCH_STATEMENT)
2143 {
2144 scanner_pop_literal_pool (context_p, scanner_context_p);
2145 }
2146 #endif /* ENABLED (JERRY_ES2015) */
2147
2148 /* A finally statement is optional after a try or catch statement. */
2149 if (context_p->token.type == LEXER_KEYW_FINALLY)
2150 {
2151 lexer_next_token (context_p);
2152
2153 if (context_p->token.type != LEXER_LEFT_BRACE)
2154 {
2155 scanner_raise_error (context_p);
2156 }
2157
2158 #if ENABLED (JERRY_ES2015)
2159 scanner_literal_pool_t *literal_pool_p;
2160 literal_pool_p = scanner_push_literal_pool (context_p,
2161 scanner_context_p,
2162 SCANNER_LITERAL_POOL_BLOCK);
2163 literal_pool_p->source_p = context_p->source_p;
2164 #endif /* ENABLED (JERRY_ES2015) */
2165
2166 parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
2167 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
2168 return SCAN_NEXT_TOKEN;
2169 }
2170
2171 if (stack_top == SCAN_STACK_CATCH_STATEMENT)
2172 {
2173 terminator_found = true;
2174 continue;
2175 }
2176
2177 /* A catch statement must be present after a try statement unless a finally is provided. */
2178 if (context_p->token.type != LEXER_KEYW_CATCH)
2179 {
2180 scanner_raise_error (context_p);
2181 }
2182
2183 lexer_next_token (context_p);
2184
2185 if (context_p->token.type != LEXER_LEFT_PAREN)
2186 {
2187 scanner_raise_error (context_p);
2188 }
2189
2190 scanner_literal_pool_t *literal_pool_p;
2191 literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_BLOCK);
2192 literal_pool_p->source_p = context_p->source_p;
2193
2194 lexer_next_token (context_p);
2195 parser_stack_push_uint8 (context_p, SCAN_STACK_CATCH_STATEMENT);
2196
2197 #if ENABLED (JERRY_ES2015)
2198 if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
2199 {
2200 scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_CATCH, false);
2201
2202 if (context_p->token.type == LEXER_LEFT_SQUARE)
2203 {
2204 parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
2205 scanner_context_p->mode = SCAN_MODE_BINDING;
2206 return SCAN_NEXT_TOKEN;
2207 }
2208
2209 parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
2210 scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
2211 return SCAN_KEEP_TOKEN;
2212 }
2213 #endif /* ENABLED (JERRY_ES2015) */
2214
2215 if (context_p->token.type != LEXER_LITERAL
2216 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
2217 {
2218 scanner_raise_error (context_p);
2219 }
2220
2221 lexer_lit_location_t *lit_location_p = scanner_add_literal (context_p, scanner_context_p);
2222 lit_location_p->type |= SCANNER_LITERAL_IS_LOCAL;
2223
2224 lexer_next_token (context_p);
2225
2226 if (context_p->token.type != LEXER_RIGHT_PAREN)
2227 {
2228 scanner_raise_error (context_p);
2229 }
2230
2231 lexer_next_token (context_p);
2232
2233 if (context_p->token.type != LEXER_LEFT_BRACE)
2234 {
2235 scanner_raise_error (context_p);
2236 }
2237
2238 scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
2239 return SCAN_NEXT_TOKEN;
2240 }
2241 }
2242
2243 if (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE))
2244 {
2245 scanner_raise_error (context_p);
2246 }
2247
2248 scanner_context_p->mode = SCAN_MODE_STATEMENT;
2249 return SCAN_KEEP_TOKEN;
2250 }
2251 } /* scanner_scan_statement_end */
2252
2253 #if defined(JERRY_FOR_IAR_CONFIG)
2254 // IAR 8.20.2 generates incorrect code for this function.
2255 // When the function is compiled with 'High:Balanced' optimization level.
2256 // In the line context_p->source_end_p = source_end_p
2257 // IAR assumes that source_end_p is in R5 register, but
2258 // the compiled doesn't initialize it since the function start.
2259 // The workaround is to compile this function without optimizations.
2260 #pragma optimize=none
2261 #endif
2262 /**
2263 * Scan the whole source code.
2264 */
2265 void JERRY_ATTR_NOINLINE
scanner_scan_all(parser_context_t * context_p,const uint8_t * arg_list_p,const uint8_t * arg_list_end_p,const uint8_t * source_p,const uint8_t * source_end_p)2266 scanner_scan_all (parser_context_t *context_p, /**< context */
2267 const uint8_t *arg_list_p, /**< function argument list */
2268 const uint8_t *arg_list_end_p, /**< end of argument list */
2269 const uint8_t *source_p, /**< valid UTF-8 source code */
2270 const uint8_t *source_end_p) /**< end of source code */
2271 {
2272 scanner_context_t scanner_context;
2273
2274 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2275 if (context_p->is_show_opcodes)
2276 {
2277 JERRY_DEBUG_MSG ("\n--- Scanning start ---\n\n");
2278 }
2279 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2280
2281 scanner_context.context_status_flags = context_p->status_flags;
2282 scanner_context.status_flags = SCANNER_CONTEXT_NO_FLAGS;
2283 #if ENABLED (JERRY_DEBUGGER)
2284 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2285 {
2286 scanner_context.status_flags |= SCANNER_CONTEXT_DEBUGGER_ENABLED;
2287 }
2288 #endif /* ENABLED (JERRY_DEBUGGER) */
2289 #if ENABLED (JERRY_ES2015)
2290 scanner_context.binding_type = SCANNER_BINDING_NONE;
2291 scanner_context.active_binding_list_p = NULL;
2292 #endif /* ENABLED (JERRY_ES2015) */
2293 scanner_context.active_literal_pool_p = NULL;
2294 scanner_context.active_switch_statement.last_case_p = NULL;
2295 scanner_context.end_arguments_p = NULL;
2296 #if ENABLED (JERRY_ES2015)
2297 scanner_context.async_source_p = NULL;
2298 #endif /* ENABLED (JERRY_ES2015) */
2299
2300 /* This assignment must be here because of Apple compilers. */
2301 context_p->u.scanner_context_p = &scanner_context;
2302
2303 parser_stack_init (context_p);
2304
2305 PARSER_TRY (context_p->try_buffer)
2306 {
2307 context_p->line = 1;
2308 context_p->column = 1;
2309
2310 if (arg_list_p == NULL)
2311 {
2312 context_p->source_p = source_p;
2313 context_p->source_end_p = source_end_p;
2314
2315 uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS | SCANNER_LITERAL_POOL_CAN_EVAL;
2316
2317 if (context_p->status_flags & PARSER_IS_STRICT)
2318 {
2319 status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
2320 }
2321
2322 scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags);
2323 literal_pool_p->source_p = source_p;
2324
2325 parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT);
2326
2327 lexer_next_token (context_p);
2328 scanner_check_directives (context_p, &scanner_context);
2329 }
2330 else
2331 {
2332 context_p->source_p = arg_list_p;
2333 context_p->source_end_p = arg_list_end_p;
2334
2335 uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
2336
2337 if (context_p->status_flags & PARSER_IS_STRICT)
2338 {
2339 status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
2340 }
2341
2342 #if ENABLED (JERRY_ES2015)
2343 if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
2344 {
2345 status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
2346 }
2347 #endif /* ENABLED (JERRY_ES2015) */
2348
2349 scanner_push_literal_pool (context_p, &scanner_context, status_flags);
2350 scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
2351 parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT_FUNCTION);
2352
2353 /* Faking the first token. */
2354 context_p->token.type = LEXER_LEFT_PAREN;
2355 }
2356
2357 while (true)
2358 {
2359 lexer_token_type_t type = (lexer_token_type_t) context_p->token.type;
2360 scan_stack_modes_t stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
2361
2362 switch (scanner_context.mode)
2363 {
2364 case SCAN_MODE_PRIMARY_EXPRESSION:
2365 {
2366 if (type == LEXER_ADD
2367 || type == LEXER_SUBTRACT
2368 || LEXER_IS_UNARY_OP_TOKEN (type))
2369 {
2370 break;
2371 }
2372 /* FALLTHRU */
2373 }
2374 case SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW:
2375 {
2376 if (scanner_scan_primary_expression (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN)
2377 {
2378 continue;
2379 }
2380 break;
2381 }
2382 #if ENABLED (JERRY_ES2015)
2383 case SCAN_MODE_CLASS_DECLARATION:
2384 {
2385 if (context_p->token.type == LEXER_KEYW_EXTENDS)
2386 {
2387 parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXTENDS);
2388 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2389 break;
2390 }
2391 else if (context_p->token.type != LEXER_LEFT_BRACE)
2392 {
2393 scanner_raise_error (context_p);
2394 }
2395
2396 scanner_context.mode = SCAN_MODE_CLASS_METHOD;
2397 /* FALLTHRU */
2398 }
2399 case SCAN_MODE_CLASS_METHOD:
2400 {
2401 JERRY_ASSERT (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR
2402 || stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR);
2403
2404 lexer_skip_empty_statements (context_p);
2405
2406 lexer_scan_identifier (context_p);
2407
2408 if (context_p->token.type == LEXER_RIGHT_BRACE)
2409 {
2410 scanner_source_start_t source_start;
2411
2412 parser_stack_pop_uint8 (context_p);
2413
2414 if (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
2415 {
2416 parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
2417 }
2418
2419 stack_top = context_p->stack_top_uint8;
2420
2421 JERRY_ASSERT (stack_top == SCAN_STACK_CLASS_STATEMENT || stack_top == SCAN_STACK_CLASS_EXPRESSION);
2422
2423 if (stack_top == SCAN_STACK_CLASS_STATEMENT)
2424 {
2425 /* The token is kept to disallow consuming a semicolon after it. */
2426 scanner_context.mode = SCAN_MODE_STATEMENT_END;
2427 continue;
2428 }
2429
2430 scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
2431 parser_stack_pop_uint8 (context_p);
2432 break;
2433 }
2434
2435 if (context_p->token.type == LEXER_LITERAL
2436 && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
2437 && lexer_compare_literal_to_string (context_p, "constructor", 11))
2438 {
2439 if (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
2440 {
2441 scanner_source_start_t source_start;
2442 parser_stack_pop_uint8 (context_p);
2443 parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
2444
2445 scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
2446 info_p->type = SCANNER_TYPE_CLASS_CONSTRUCTOR;
2447 parser_stack_push_uint8 (context_p, SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR);
2448 }
2449 }
2450
2451 if (lexer_token_is_identifier (context_p, "static", 6))
2452 {
2453 lexer_scan_identifier (context_p);
2454 }
2455
2456 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
2457 scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
2458
2459 uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION;
2460
2461 if (lexer_token_is_identifier (context_p, "get", 3)
2462 || lexer_token_is_identifier (context_p, "set", 3))
2463 {
2464 lexer_scan_identifier (context_p);
2465
2466 if (context_p->token.type == LEXER_LEFT_PAREN)
2467 {
2468 scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
2469 continue;
2470 }
2471 }
2472 else if (lexer_token_is_identifier (context_p, "async", 5))
2473 {
2474 lexer_scan_identifier (context_p);
2475
2476 if (context_p->token.type == LEXER_LEFT_PAREN)
2477 {
2478 scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
2479 continue;
2480 }
2481
2482 literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC;
2483
2484 if (context_p->token.type == LEXER_MULTIPLY)
2485 {
2486 lexer_scan_identifier (context_p);
2487 literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
2488 }
2489 }
2490 else if (context_p->token.type == LEXER_MULTIPLY)
2491 {
2492 lexer_scan_identifier (context_p);
2493 literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
2494 }
2495
2496 if (context_p->token.type == LEXER_LEFT_SQUARE)
2497 {
2498 parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
2499 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2500 break;
2501 }
2502
2503 if (context_p->token.type != LEXER_LITERAL)
2504 {
2505 scanner_raise_error (context_p);
2506 }
2507
2508 if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR)
2509 {
2510 context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
2511 }
2512
2513 scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags);
2514 lexer_next_token (context_p);
2515 continue;
2516 }
2517 #endif /* ENABLED (JERRY_ES2015) */
2518 case SCAN_MODE_POST_PRIMARY_EXPRESSION:
2519 {
2520 if (scanner_scan_post_primary_expression (context_p, &scanner_context, type, stack_top))
2521 {
2522 break;
2523 }
2524 type = (lexer_token_type_t) context_p->token.type;
2525 /* FALLTHRU */
2526 }
2527 case SCAN_MODE_PRIMARY_EXPRESSION_END:
2528 {
2529 if (scanner_scan_primary_expression_end (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN)
2530 {
2531 continue;
2532 }
2533 break;
2534 }
2535 case SCAN_MODE_STATEMENT_OR_TERMINATOR:
2536 {
2537 if (type == LEXER_RIGHT_BRACE || type == LEXER_EOS)
2538 {
2539 scanner_context.mode = SCAN_MODE_STATEMENT_END;
2540 continue;
2541 }
2542 /* FALLTHRU */
2543 }
2544 case SCAN_MODE_STATEMENT:
2545 {
2546 if (scanner_scan_statement (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN)
2547 {
2548 continue;
2549 }
2550 break;
2551 }
2552 case SCAN_MODE_STATEMENT_END:
2553 {
2554 if (scanner_scan_statement_end (context_p, &scanner_context, type) != SCAN_NEXT_TOKEN)
2555 {
2556 continue;
2557 }
2558
2559 if (context_p->token.type == LEXER_EOS)
2560 {
2561 goto scan_completed;
2562 }
2563
2564 break;
2565 }
2566 case SCAN_MODE_VAR_STATEMENT:
2567 {
2568 #if ENABLED (JERRY_ES2015)
2569 if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE)
2570 {
2571 uint8_t binding_type = SCANNER_BINDING_VAR;
2572
2573 if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START)
2574 {
2575 binding_type = SCANNER_BINDING_LET;
2576 }
2577 else if (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START)
2578 {
2579 binding_type = SCANNER_BINDING_CONST;
2580 }
2581
2582 scanner_push_destructuring_pattern (context_p, &scanner_context, binding_type, false);
2583
2584 if (type == LEXER_LEFT_SQUARE)
2585 {
2586 parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
2587 scanner_context.mode = SCAN_MODE_BINDING;
2588 break;
2589 }
2590
2591 parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
2592 scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
2593 continue;
2594 }
2595 #endif /* ENABLED (JERRY_ES2015) */
2596
2597 if (type != LEXER_LITERAL
2598 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
2599 {
2600 scanner_raise_error (context_p);
2601 }
2602
2603 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context);
2604
2605 #if ENABLED (JERRY_ES2015)
2606 if (stack_top != SCAN_STACK_VAR && stack_top != SCAN_STACK_FOR_VAR_START)
2607 {
2608 scanner_detect_invalid_let (context_p, literal_p);
2609
2610 if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START)
2611 {
2612 literal_p->type |= SCANNER_LITERAL_IS_LET;
2613 }
2614 else
2615 {
2616 JERRY_ASSERT (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START);
2617 literal_p->type |= SCANNER_LITERAL_IS_CONST;
2618 }
2619
2620 lexer_next_token (context_p);
2621
2622 if (literal_p->type & SCANNER_LITERAL_IS_USED)
2623 {
2624 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
2625 }
2626 else if (context_p->token.type == LEXER_ASSIGN)
2627 {
2628 scanner_binding_literal_t binding_literal;
2629 binding_literal.literal_p = literal_p;
2630
2631 parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
2632 parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
2633 }
2634 }
2635 else
2636 {
2637 if (!(literal_p->type & SCANNER_LITERAL_IS_VAR))
2638 {
2639 scanner_detect_invalid_var (context_p, &scanner_context, literal_p);
2640 literal_p->type |= SCANNER_LITERAL_IS_VAR;
2641
2642 if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
2643 {
2644 literal_p->type |= SCANNER_LITERAL_NO_REG;
2645 }
2646 }
2647
2648 lexer_next_token (context_p);
2649 }
2650 #else /* !ENABLED (JERRY_ES2015) */
2651 literal_p->type |= SCANNER_LITERAL_IS_VAR;
2652
2653 if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
2654 {
2655 literal_p->type |= SCANNER_LITERAL_NO_REG;
2656 }
2657
2658 lexer_next_token (context_p);
2659 #endif /* ENABLED (JERRY_ES2015) */
2660
2661 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2662 if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT)
2663 {
2664 literal_p->type |= SCANNER_LITERAL_NO_REG;
2665 }
2666 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2667
2668 switch (context_p->token.type)
2669 {
2670 case LEXER_ASSIGN:
2671 {
2672 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2673 /* FALLTHRU */
2674 }
2675 case LEXER_COMMA:
2676 {
2677 lexer_next_token (context_p);
2678 continue;
2679 }
2680 }
2681
2682 if (SCANNER_IS_FOR_START (stack_top))
2683 {
2684 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2685 JERRY_ASSERT (!(scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT));
2686 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2687
2688 if (context_p->token.type != LEXER_SEMICOLON
2689 && context_p->token.type != LEXER_KEYW_IN
2690 && !SCANNER_IDENTIFIER_IS_OF ())
2691 {
2692 scanner_raise_error (context_p);
2693 }
2694
2695 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
2696 continue;
2697 }
2698
2699 #if ENABLED (JERRY_ES2015)
2700 JERRY_ASSERT (stack_top == SCAN_STACK_VAR || stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST);
2701 #else /* !ENABLED (JERRY_ES2015) */
2702 JERRY_ASSERT (stack_top == SCAN_STACK_VAR);
2703 #endif /* ENABLED (JERRY_ES2015) */
2704
2705 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2706 scanner_context.active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
2707 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2708
2709 scanner_context.mode = SCAN_MODE_STATEMENT_END;
2710 parser_stack_pop_uint8 (context_p);
2711 continue;
2712 }
2713 case SCAN_MODE_FUNCTION_ARGUMENTS:
2714 {
2715 JERRY_ASSERT (stack_top == SCAN_STACK_SCRIPT_FUNCTION
2716 || stack_top == SCAN_STACK_FUNCTION_STATEMENT
2717 || stack_top == SCAN_STACK_FUNCTION_EXPRESSION
2718 || stack_top == SCAN_STACK_FUNCTION_PROPERTY);
2719
2720 scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p;
2721
2722 JERRY_ASSERT (literal_pool_p != NULL && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION));
2723
2724 literal_pool_p->source_p = context_p->source_p;
2725
2726 #if ENABLED (JERRY_ES2015)
2727 if (JERRY_UNLIKELY (scanner_context.async_source_p != NULL))
2728 {
2729 literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ASYNC;
2730 literal_pool_p->source_p = scanner_context.async_source_p;
2731 scanner_context.async_source_p = NULL;
2732 }
2733 #endif /* ENABLED (JERRY_ES2015) */
2734
2735 if (type != LEXER_LEFT_PAREN)
2736 {
2737 scanner_raise_error (context_p);
2738 }
2739 lexer_next_token (context_p);
2740
2741 #if ENABLED (JERRY_ES2015)
2742 /* FALLTHRU */
2743 }
2744 case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS:
2745 {
2746 #endif /* ENABLED (JERRY_ES2015) */
2747 if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS)
2748 {
2749 #if ENABLED (JERRY_ES2015)
2750 lexer_lit_location_t *argument_literal_p;
2751 #endif /* ENABLED (JERRY_ES2015) */
2752
2753 while (true)
2754 {
2755 #if ENABLED (JERRY_ES2015)
2756 if (context_p->token.type == LEXER_THREE_DOTS)
2757 {
2758 scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
2759
2760 lexer_next_token (context_p);
2761 }
2762
2763 if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
2764 {
2765 argument_literal_p = NULL;
2766 break;
2767 }
2768 #endif /* ENABLED (JERRY_ES2015) */
2769
2770 if (context_p->token.type != LEXER_LITERAL
2771 || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
2772 {
2773 scanner_raise_error (context_p);
2774 }
2775
2776 #if ENABLED (JERRY_ES2015)
2777 argument_literal_p = scanner_append_argument (context_p, &scanner_context);
2778 #else /* !ENABLED (JERRY_ES2015) */
2779 scanner_append_argument (context_p, &scanner_context);
2780 #endif /* ENABLED (JERRY_ES2015) */
2781
2782 lexer_next_token (context_p);
2783
2784 if (context_p->token.type != LEXER_COMMA)
2785 {
2786 break;
2787 }
2788 lexer_next_token (context_p);
2789 }
2790
2791 #if ENABLED (JERRY_ES2015)
2792 if (argument_literal_p == NULL)
2793 {
2794 scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
2795
2796 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
2797 scanner_append_hole (context_p, &scanner_context);
2798 scanner_push_destructuring_pattern (context_p, &scanner_context, SCANNER_BINDING_ARG, false);
2799
2800 if (context_p->token.type == LEXER_LEFT_SQUARE)
2801 {
2802 parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
2803 scanner_context.mode = SCAN_MODE_BINDING;
2804 break;
2805 }
2806
2807 parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
2808 scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
2809 continue;
2810 }
2811
2812 if (context_p->token.type == LEXER_ASSIGN)
2813 {
2814 scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
2815
2816 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
2817 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2818
2819 if (argument_literal_p->type & SCANNER_LITERAL_IS_USED)
2820 {
2821 JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE);
2822 break;
2823 }
2824
2825 scanner_binding_literal_t binding_literal;
2826 binding_literal.literal_p = argument_literal_p;
2827
2828 parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
2829 parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
2830 break;
2831 }
2832 #endif /* ENABLED (JERRY_ES2015) */
2833 }
2834
2835 if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_SCRIPT_FUNCTION)
2836 {
2837 /* End of argument parsing. */
2838 scanner_info_t *scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, sizeof (scanner_info_t));
2839 scanner_info_p->next_p = context_p->next_scanner_info_p;
2840 scanner_info_p->source_p = NULL;
2841 scanner_info_p->type = SCANNER_TYPE_END_ARGUMENTS;
2842 scanner_context.end_arguments_p = scanner_info_p;
2843
2844 context_p->next_scanner_info_p = scanner_info_p;
2845 context_p->source_p = source_p;
2846 context_p->source_end_p = source_end_p;
2847 context_p->line = 1;
2848 context_p->column = 1;
2849
2850 scanner_filter_arguments (context_p, &scanner_context);
2851 lexer_next_token (context_p);
2852 scanner_check_directives (context_p, &scanner_context);
2853 continue;
2854 }
2855
2856 if (context_p->token.type != LEXER_RIGHT_PAREN)
2857 {
2858 scanner_raise_error (context_p);
2859 }
2860
2861 lexer_next_token (context_p);
2862
2863 if (context_p->token.type != LEXER_LEFT_BRACE)
2864 {
2865 scanner_raise_error (context_p);
2866 }
2867
2868 scanner_filter_arguments (context_p, &scanner_context);
2869 lexer_next_token (context_p);
2870 scanner_check_directives (context_p, &scanner_context);
2871 continue;
2872 }
2873 case SCAN_MODE_PROPERTY_NAME:
2874 {
2875 JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL);
2876
2877 if (lexer_scan_identifier (context_p))
2878 {
2879 lexer_check_property_modifier (context_p);
2880 }
2881
2882 #if ENABLED (JERRY_ES2015)
2883 if (context_p->token.type == LEXER_LEFT_SQUARE)
2884 {
2885 parser_stack_push_uint8 (context_p, SCAN_STACK_COMPUTED_PROPERTY);
2886 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2887 break;
2888 }
2889 #endif /* ENABLED (JERRY_ES2015) */
2890
2891 if (context_p->token.type == LEXER_RIGHT_BRACE)
2892 {
2893 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
2894 continue;
2895 }
2896
2897 if (context_p->token.type == LEXER_PROPERTY_GETTER
2898 #if ENABLED (JERRY_ES2015)
2899 || context_p->token.type == LEXER_KEYW_ASYNC
2900 || context_p->token.type == LEXER_MULTIPLY
2901 #endif /* ENABLED (JERRY_ES2015) */
2902 || context_p->token.type == LEXER_PROPERTY_SETTER)
2903 {
2904 uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION;
2905
2906 #if ENABLED (JERRY_ES2015)
2907 if (context_p->token.type == LEXER_MULTIPLY)
2908 {
2909 literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
2910 }
2911 else if (context_p->token.type == LEXER_KEYW_ASYNC)
2912 {
2913 literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC;
2914
2915 if (lexer_consume_generator (context_p))
2916 {
2917 literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
2918 }
2919 }
2920 #endif /* ENABLED (JERRY_ES2015) */
2921
2922 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
2923 lexer_scan_identifier (context_p);
2924
2925 #if ENABLED (JERRY_ES2015)
2926 if (context_p->token.type == LEXER_LEFT_SQUARE)
2927 {
2928 parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
2929 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2930 break;
2931 }
2932 #endif /* ENABLED (JERRY_ES2015) */
2933
2934 if (context_p->token.type != LEXER_LITERAL)
2935 {
2936 scanner_raise_error (context_p);
2937 }
2938
2939 scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags);
2940 scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
2941 break;
2942 }
2943
2944 if (context_p->token.type != LEXER_LITERAL)
2945 {
2946 scanner_raise_error (context_p);
2947 }
2948
2949 #if ENABLED (JERRY_ES2015)
2950 parser_line_counter_t start_line = context_p->token.line;
2951 parser_line_counter_t start_column = context_p->token.column;
2952 bool is_ident = (context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
2953 #endif /* ENABLED (JERRY_ES2015) */
2954
2955 lexer_next_token (context_p);
2956
2957 #if ENABLED (JERRY_ES2015)
2958 if (context_p->token.type == LEXER_LEFT_PAREN)
2959 {
2960 scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
2961
2962 parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
2963 scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
2964 continue;
2965 }
2966
2967 if (is_ident
2968 && (context_p->token.type == LEXER_COMMA
2969 || context_p->token.type == LEXER_RIGHT_BRACE
2970 || context_p->token.type == LEXER_ASSIGN))
2971 {
2972 context_p->source_p = context_p->token.lit_location.char_p;
2973 context_p->line = start_line;
2974 context_p->column = start_column;
2975
2976 lexer_next_token (context_p);
2977
2978 JERRY_ASSERT (context_p->token.type != LEXER_LITERAL
2979 || context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
2980
2981 if (context_p->token.type != LEXER_LITERAL)
2982 {
2983 scanner_raise_error (context_p);
2984 }
2985
2986 if (scanner_context.binding_type != SCANNER_BINDING_NONE)
2987 {
2988 scanner_context.mode = SCAN_MODE_BINDING;
2989 continue;
2990 }
2991
2992 scanner_add_reference (context_p, &scanner_context);
2993
2994 lexer_next_token (context_p);
2995
2996 if (context_p->token.type == LEXER_ASSIGN)
2997 {
2998 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
2999 break;
3000 }
3001
3002 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
3003 continue;
3004 }
3005 #endif /* ENABLED (JERRY_ES2015) */
3006
3007 if (context_p->token.type != LEXER_COLON)
3008 {
3009 scanner_raise_error (context_p);
3010 }
3011
3012 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
3013
3014 #if ENABLED (JERRY_ES2015)
3015 if (scanner_context.binding_type != SCANNER_BINDING_NONE)
3016 {
3017 scanner_context.mode = SCAN_MODE_BINDING;
3018 }
3019 #endif /* ENABLED (JERRY_ES2015) */
3020 break;
3021 }
3022 #if ENABLED (JERRY_ES2015)
3023 case SCAN_MODE_BINDING:
3024 {
3025 JERRY_ASSERT (scanner_context.binding_type == SCANNER_BINDING_VAR
3026 || scanner_context.binding_type == SCANNER_BINDING_LET
3027 || scanner_context.binding_type == SCANNER_BINDING_CATCH
3028 || scanner_context.binding_type == SCANNER_BINDING_CONST
3029 || scanner_context.binding_type == SCANNER_BINDING_ARG
3030 || scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG);
3031
3032 if (type == LEXER_THREE_DOTS)
3033 {
3034 lexer_next_token (context_p);
3035 type = (lexer_token_type_t) context_p->token.type;
3036 }
3037
3038 if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE)
3039 {
3040 scanner_push_destructuring_pattern (context_p, &scanner_context, scanner_context.binding_type, true);
3041
3042 if (type == LEXER_LEFT_SQUARE)
3043 {
3044 parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
3045 break;
3046 }
3047
3048 parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
3049 scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
3050 continue;
3051 }
3052
3053 if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
3054 {
3055 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
3056 continue;
3057 }
3058
3059 lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context);
3060
3061 scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
3062
3063 if (scanner_context.binding_type == SCANNER_BINDING_VAR)
3064 {
3065 if (!(literal_p->type & SCANNER_LITERAL_IS_VAR))
3066 {
3067 scanner_detect_invalid_var (context_p, &scanner_context, literal_p);
3068 literal_p->type |= SCANNER_LITERAL_IS_VAR;
3069
3070 if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
3071 {
3072 literal_p->type |= SCANNER_LITERAL_NO_REG;
3073 }
3074 }
3075 break;
3076 }
3077
3078 if (scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG)
3079 {
3080 literal_p->type |= SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
3081
3082 if (literal_p->type & SCANNER_LITERAL_IS_USED)
3083 {
3084 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
3085 break;
3086 }
3087 }
3088 else
3089 {
3090 scanner_detect_invalid_let (context_p, literal_p);
3091
3092 if (scanner_context.binding_type <= SCANNER_BINDING_CATCH)
3093 {
3094 JERRY_ASSERT ((scanner_context.binding_type == SCANNER_BINDING_LET)
3095 || (scanner_context.binding_type == SCANNER_BINDING_CATCH));
3096
3097 literal_p->type |= SCANNER_LITERAL_IS_LET;
3098 }
3099 else
3100 {
3101 literal_p->type |= SCANNER_LITERAL_IS_CONST;
3102
3103 if (scanner_context.binding_type == SCANNER_BINDING_ARG)
3104 {
3105 literal_p->type |= SCANNER_LITERAL_IS_ARG;
3106
3107 if (literal_p->type & SCANNER_LITERAL_IS_USED)
3108 {
3109 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
3110 break;
3111 }
3112 }
3113 }
3114
3115 if (literal_p->type & SCANNER_LITERAL_IS_USED)
3116 {
3117 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
3118 break;
3119 }
3120 }
3121
3122 scanner_binding_item_t *binding_item_p;
3123 binding_item_p = (scanner_binding_item_t *) scanner_malloc (context_p, sizeof (scanner_binding_item_t));
3124
3125 binding_item_p->next_p = scanner_context.active_binding_list_p->items_p;
3126 binding_item_p->literal_p = literal_p;
3127
3128 scanner_context.active_binding_list_p->items_p = binding_item_p;
3129
3130 lexer_next_token (context_p);
3131 if (context_p->token.type != LEXER_ASSIGN)
3132 {
3133 continue;
3134 }
3135
3136 scanner_binding_literal_t binding_literal;
3137 binding_literal.literal_p = literal_p;
3138
3139 parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
3140 parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
3141
3142 scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
3143 break;
3144 }
3145 #endif /* ENABLED (JERRY_ES2015) */
3146 }
3147
3148 lexer_next_token (context_p);
3149 }
3150
3151 scan_completed:
3152 if (context_p->stack_top_uint8 != SCAN_STACK_SCRIPT
3153 && context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION)
3154 {
3155 scanner_raise_error (context_p);
3156 }
3157
3158 scanner_pop_literal_pool (context_p, &scanner_context);
3159
3160 #if ENABLED (JERRY_ES2015)
3161 JERRY_ASSERT (scanner_context.active_binding_list_p == NULL);
3162 #endif /* ENABLED (JERRY_ES2015) */
3163 JERRY_ASSERT (scanner_context.active_literal_pool_p == NULL);
3164
3165 #ifndef JERRY_NDEBUG
3166 scanner_context.context_status_flags |= PARSER_SCANNING_SUCCESSFUL;
3167 #endif /* !JERRY_NDEBUG */
3168 }
3169 PARSER_CATCH
3170 {
3171 #if ENABLED (JERRY_ES2015)
3172 while (scanner_context.active_binding_list_p != NULL)
3173 {
3174 scanner_pop_binding_list (&scanner_context);
3175 }
3176 #endif /* ENABLED (JERRY_ES2015) */
3177
3178 if (JERRY_UNLIKELY (context_p->error != PARSER_ERR_OUT_OF_MEMORY))
3179 {
3180 /* Ignore the errors thrown by the lexer. */
3181 context_p->error = PARSER_ERR_NO_ERROR;
3182
3183 /* The following code may allocate memory, so it is enclosed in a try/catch. */
3184 PARSER_TRY (context_p->try_buffer)
3185 {
3186 #if ENABLED (JERRY_ES2015)
3187 if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION)
3188 {
3189 JERRY_ASSERT (scanner_context.async_source_p != NULL);
3190
3191 scanner_info_t *info_p;
3192 info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t));
3193 info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION;
3194 }
3195 #endif /* ENABLED (JERRY_ES2015) */
3196
3197 while (scanner_context.active_literal_pool_p != NULL)
3198 {
3199 scanner_pop_literal_pool (context_p, &scanner_context);
3200 }
3201 }
3202 PARSER_CATCH
3203 {
3204 JERRY_ASSERT (context_p->error == PARSER_ERR_OUT_OF_MEMORY);
3205 }
3206 PARSER_TRY_END
3207 }
3208
3209 JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR || context_p->error == PARSER_ERR_OUT_OF_MEMORY);
3210
3211 if (context_p->error == PARSER_ERR_OUT_OF_MEMORY)
3212 {
3213 while (scanner_context.active_literal_pool_p != NULL)
3214 {
3215 scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p;
3216
3217 scanner_context.active_literal_pool_p = literal_pool_p->prev_p;
3218
3219 parser_list_free (&literal_pool_p->literal_pool);
3220 scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
3221 }
3222
3223 parser_stack_free (context_p);
3224 return;
3225 }
3226 }
3227 PARSER_TRY_END
3228
3229 context_p->status_flags = scanner_context.context_status_flags;
3230 scanner_reverse_info_list (context_p);
3231
3232 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
3233 if (context_p->is_show_opcodes)
3234 {
3235 scanner_info_t *info_p = context_p->next_scanner_info_p;
3236 const uint8_t *source_start_p = (arg_list_p == NULL) ? source_p : arg_list_p;
3237
3238 while (info_p->type != SCANNER_TYPE_END)
3239 {
3240 const char *name_p = NULL;
3241 bool print_location = false;
3242
3243 switch (info_p->type)
3244 {
3245 case SCANNER_TYPE_END_ARGUMENTS:
3246 {
3247 JERRY_DEBUG_MSG (" END_ARGUMENTS\n");
3248 source_start_p = source_p;
3249 break;
3250 }
3251 case SCANNER_TYPE_FUNCTION:
3252 case SCANNER_TYPE_BLOCK:
3253 {
3254 const uint8_t *prev_source_p = info_p->source_p - 1;
3255 const uint8_t *data_p;
3256
3257 if (info_p->type == SCANNER_TYPE_FUNCTION)
3258 {
3259 data_p = (const uint8_t *) (info_p + 1);
3260
3261 JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d",
3262 (int) info_p->u8_arg,
3263 (int) info_p->u16_arg);
3264 }
3265 else
3266 {
3267 data_p = (const uint8_t *) (info_p + 1);
3268
3269 JERRY_DEBUG_MSG (" BLOCK:");
3270 }
3271
3272 JERRY_DEBUG_MSG (" source:%d\n", (int) (info_p->source_p - source_start_p));
3273
3274 while (data_p[0] != SCANNER_STREAM_TYPE_END)
3275 {
3276 switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
3277 {
3278 case SCANNER_STREAM_TYPE_VAR:
3279 {
3280 JERRY_DEBUG_MSG (" VAR ");
3281 break;
3282 }
3283 #if ENABLED (JERRY_ES2015)
3284 case SCANNER_STREAM_TYPE_LET:
3285 {
3286 JERRY_DEBUG_MSG (" LET ");
3287 break;
3288 }
3289 case SCANNER_STREAM_TYPE_CONST:
3290 {
3291 JERRY_DEBUG_MSG (" CONST ");
3292 break;
3293 }
3294 case SCANNER_STREAM_TYPE_LOCAL:
3295 {
3296 JERRY_DEBUG_MSG (" LOCAL ");
3297 break;
3298 }
3299 #endif /* ENABLED (JERRY_ES2015) */
3300 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
3301 case SCANNER_STREAM_TYPE_IMPORT:
3302 {
3303 JERRY_DEBUG_MSG (" IMPORT ");
3304 break;
3305 }
3306 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
3307 case SCANNER_STREAM_TYPE_ARG:
3308 {
3309 JERRY_DEBUG_MSG (" ARG ");
3310 break;
3311 }
3312 #if ENABLED (JERRY_ES2015)
3313 case SCANNER_STREAM_TYPE_ARG_VAR:
3314 {
3315 JERRY_DEBUG_MSG (" ARG_VAR ");
3316 break;
3317 }
3318 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
3319 {
3320 JERRY_DEBUG_MSG (" DESTRUCTURED_ARG ");
3321 break;
3322 }
3323 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
3324 {
3325 JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_VAR ");
3326 break;
3327 }
3328 #endif /* ENABLED (JERRY_ES2015) */
3329 case SCANNER_STREAM_TYPE_ARG_FUNC:
3330 {
3331 JERRY_DEBUG_MSG (" ARG_FUNC ");
3332 break;
3333 }
3334 #if ENABLED (JERRY_ES2015)
3335 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
3336 {
3337 JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_FUNC ");
3338 break;
3339 }
3340 #endif /* ENABLED (JERRY_ES2015) */
3341 case SCANNER_STREAM_TYPE_FUNC:
3342 {
3343 JERRY_DEBUG_MSG (" FUNC ");
3344 break;
3345 }
3346 default:
3347 {
3348 JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
3349 JERRY_DEBUG_MSG (" HOLE\n");
3350 data_p++;
3351 continue;
3352 }
3353 }
3354
3355 size_t length;
3356
3357 if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
3358 {
3359 if (data_p[2] != 0)
3360 {
3361 prev_source_p += data_p[2];
3362 length = 2 + 1;
3363 }
3364 else
3365 {
3366 memcpy (&prev_source_p, data_p + 2 + 1, sizeof (const uint8_t *));
3367 length = 2 + 1 + sizeof (const uint8_t *);
3368 }
3369 }
3370 else
3371 {
3372 int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
3373
3374 if (diff <= UINT8_MAX)
3375 {
3376 diff = -diff;
3377 }
3378
3379 prev_source_p += diff;
3380 length = 2 + 2;
3381 }
3382
3383 #if ENABLED (JERRY_ES2015)
3384 if (data_p[0] & SCANNER_STREAM_EARLY_CREATE)
3385 {
3386 JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG);
3387 JERRY_DEBUG_MSG ("*");
3388 }
3389 #endif /* ENABLED (JERRY_ES2015) */
3390
3391 if (data_p[0] & SCANNER_STREAM_NO_REG)
3392 {
3393 JERRY_DEBUG_MSG ("* ");
3394 }
3395
3396 JERRY_DEBUG_MSG ("'%.*s'\n", data_p[1], (char *) prev_source_p);
3397 prev_source_p += data_p[1];
3398 data_p += length;
3399 }
3400 break;
3401 }
3402 case SCANNER_TYPE_WHILE:
3403 {
3404 name_p = "WHILE";
3405 print_location = true;
3406 break;
3407 }
3408 case SCANNER_TYPE_FOR:
3409 {
3410 scanner_for_info_t *for_info_p = (scanner_for_info_t *) info_p;
3411 JERRY_DEBUG_MSG (" FOR: source:%d expression:%d[%d:%d] end:%d[%d:%d]\n",
3412 (int) (for_info_p->info.source_p - source_start_p),
3413 (int) (for_info_p->expression_location.source_p - source_start_p),
3414 (int) for_info_p->expression_location.line,
3415 (int) for_info_p->expression_location.column,
3416 (int) (for_info_p->end_location.source_p - source_start_p),
3417 (int) for_info_p->end_location.line,
3418 (int) for_info_p->end_location.column);
3419 break;
3420 }
3421 case SCANNER_TYPE_FOR_IN:
3422 {
3423 name_p = "FOR-IN";
3424 print_location = true;
3425 break;
3426 }
3427 #if ENABLED (JERRY_ES2015)
3428 case SCANNER_TYPE_FOR_OF:
3429 {
3430 name_p = "FOR-OF";
3431 print_location = true;
3432 break;
3433 }
3434 #endif /* ENABLED (JERRY_ES2015) */
3435 case SCANNER_TYPE_SWITCH:
3436 {
3437 JERRY_DEBUG_MSG (" SWITCH: source:%d\n",
3438 (int) (info_p->source_p - source_start_p));
3439
3440 scanner_case_info_t *current_case_p = ((scanner_switch_info_t *) info_p)->case_p;
3441
3442 while (current_case_p != NULL)
3443 {
3444 JERRY_DEBUG_MSG (" CASE: location:%d[%d:%d]\n",
3445 (int) (current_case_p->location.source_p - source_start_p),
3446 (int) current_case_p->location.line,
3447 (int) current_case_p->location.column);
3448
3449 current_case_p = current_case_p->next_p;
3450 }
3451 break;
3452 }
3453 case SCANNER_TYPE_CASE:
3454 {
3455 name_p = "CASE";
3456 print_location = true;
3457 break;
3458 }
3459 #if ENABLED (JERRY_ES2015)
3460 case SCANNER_TYPE_INITIALIZER:
3461 {
3462 name_p = "INITIALIZER";
3463 print_location = true;
3464 break;
3465 }
3466 case SCANNER_TYPE_CLASS_CONSTRUCTOR:
3467 {
3468 JERRY_DEBUG_MSG (" CLASS-CONSTRUCTOR: source:%d\n",
3469 (int) (info_p->source_p - source_start_p));
3470 print_location = false;
3471 break;
3472 }
3473 case SCANNER_TYPE_LET_EXPRESSION:
3474 {
3475 JERRY_DEBUG_MSG (" LET_EXPRESSION: source:%d\n",
3476 (int) (info_p->source_p - source_start_p));
3477 break;
3478 }
3479 case SCANNER_TYPE_ERR_REDECLARED:
3480 {
3481 JERRY_DEBUG_MSG (" ERR_REDECLARED: source:%d\n",
3482 (int) (info_p->source_p - source_start_p));
3483 break;
3484 }
3485 case SCANNER_TYPE_ERR_ASYNC_FUNCTION:
3486 {
3487 JERRY_DEBUG_MSG (" ERR_ASYNC_FUNCTION: source:%d\n",
3488 (int) (info_p->source_p - source_start_p));
3489 break;
3490 }
3491 #endif /* ENABLED (JERRY_ES2015) */
3492 }
3493
3494 if (print_location)
3495 {
3496 scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p;
3497 JERRY_DEBUG_MSG (" %s: source:%d location:%d[%d:%d]\n",
3498 name_p,
3499 (int) (location_info_p->info.source_p - source_start_p),
3500 (int) (location_info_p->location.source_p - source_start_p),
3501 (int) location_info_p->location.line,
3502 (int) location_info_p->location.column);
3503 }
3504
3505 info_p = info_p->next_p;
3506 }
3507
3508 JERRY_DEBUG_MSG ("\n--- Scanning end ---\n\n");
3509 }
3510 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
3511
3512 parser_stack_free (context_p);
3513 } /* scanner_scan_all */
3514
3515 /**
3516 * @}
3517 * @}
3518 * @}
3519 */
3520
3521 #endif /* ENABLED (JERRY_PARSER) */
3522