• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "js-parser-internal.h"
17 
18 #if ENABLED (JERRY_PARSER)
19 #include "jcontext.h"
20 
21 #include "ecma-helpers.h"
22 #include "lit-char-helpers.h"
23 #include "js-parser-tagged-template-literal.h"
24 
25 /** \addtogroup parser Parser
26  * @{
27  *
28  * \addtogroup jsparser JavaScript
29  * @{
30  *
31  * \addtogroup jsparser_expr Expression parser
32  * @{
33  */
34 
35 /**
36  * Maximum precedence for right-to-left binary operation evaluation.
37  */
38 #define PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE 6
39 
40 /**
41  * Precedence for ternary operation.
42  */
43 #define PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE 4
44 
45 /**
46  * Precedence for exponentiation operation.
47  */
48 #define PARSER_RIGHT_TO_LEFT_ORDER_EXPONENTIATION 15
49 
50 /**
51  * Value of grouping level increase and decrease.
52  */
53 #define PARSER_GROUPING_LEVEL_INCREASE 2
54 
55 /**
56  * Precedence of the binary tokens.
57  *
58  * See also:
59  *    lexer_token_type_t
60  */
61 static const uint8_t parser_binary_precedence_table[] =
62 {
63   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
64 #if ENABLED (JERRY_ES2015)
65   3,
66 #endif /* ENABLED (JERRY_ES2015) */
67   4, 5, 6, 7, 8, 9, 10, 10, 10, 10,
68   11, 11, 11, 11, 11, 11, 12, 12, 12,
69   13, 13, 14, 14, 14,
70 #if ENABLED (JERRY_ES2015)
71   15,
72 #endif /* ENABLED (JERRY_ES2015) */
73 };
74 
75 #if ENABLED (JERRY_ES2015)
76 JERRY_STATIC_ASSERT (sizeof (parser_binary_precedence_table) == 38,
77                      parser_binary_precedence_table_should_have_38_values_in_es2015);
78 #else /* !ENABLED (JERRY_ES2015) */
79 JERRY_STATIC_ASSERT (sizeof (parser_binary_precedence_table) == 36,
80                      parser_binary_precedence_table_should_have_36_values_in_es51);
81 #endif /* ENABLED (JERRY_ES2015) */
82 
83 /**
84  * Generate byte code for operators with lvalue.
85  */
86 static inline void
parser_push_result(parser_context_t * context_p)87 parser_push_result (parser_context_t *context_p) /**< context */
88 {
89   if (CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode))
90   {
91     JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, context_p->last_cbc_opcode + 1));
92 
93     if ((context_p->last_cbc_opcode == CBC_POST_INCR
94          || context_p->last_cbc_opcode == CBC_POST_DECR)
95         && context_p->stack_depth >= context_p->stack_limit)
96     {
97       /* Stack limit is increased for CBC_POST_INCR_PUSH_RESULT
98        * and CBC_POST_DECR_PUSH_RESULT opcodes. Needed by vm.c. */
99       JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit);
100 
101       context_p->stack_limit++;
102 
103       if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT)
104       {
105         parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
106       }
107     }
108 
109     context_p->last_cbc_opcode++;
110     parser_flush_cbc (context_p);
111   }
112 } /* parser_push_result */
113 
114 /**
115  * Check for invalid assignment for "eval" and "arguments"
116  */
117 static void
parser_check_invalid_assign(parser_context_t * context_p)118 parser_check_invalid_assign (parser_context_t *context_p) /**< context */
119 {
120   JERRY_ASSERT (context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL);
121 
122   if (JERRY_UNLIKELY (context_p->status_flags & PARSER_IS_STRICT))
123   {
124     if (context_p->last_cbc.literal_keyword_type == LEXER_KEYW_EVAL)
125     {
126       parser_raise_error (context_p, PARSER_ERR_EVAL_CANNOT_ASSIGNED);
127     }
128     else if (context_p->last_cbc.literal_keyword_type == LEXER_KEYW_ARGUMENTS)
129     {
130       parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_CANNOT_ASSIGNED);
131     }
132   }
133 } /* parser_check_invalid_assign */
134 
135 #if ENABLED (JERRY_ES2015)
136 
137 /**
138  * Check and throw an error if the "new.target" is invalid as a left-hand side expression.
139  */
140 static void
parser_check_invalid_new_target(parser_context_t * context_p,cbc_opcode_t opcode)141 parser_check_invalid_new_target (parser_context_t *context_p, /**< parser context */
142                                  cbc_opcode_t opcode) /**< current opcode under parsing */
143 {
144   /* new.target is an invalid left-hand side target */
145   if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_NEW_TARGET))
146   {
147     /* Make sure that the call side is a post/pre increment or an assignment expression.
148      * There should be no other ways the "new.target" expression should be here. */
149     JERRY_ASSERT ((opcode >= CBC_PRE_INCR && opcode <= CBC_POST_DECR)
150                   || (opcode == CBC_ASSIGN
151                       && (context_p->token.type == LEXER_ASSIGN
152                           || LEXER_IS_BINARY_LVALUE_TOKEN (context_p->token.type))));
153 
154     parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED);
155   }
156 } /* parser_check_invalid_new_target */
157 
158 #endif /* ENABLED (JERRY_ES2015) */
159 
160 /**
161  * Emit identifier reference
162  */
163 static void
parser_emit_ident_reference(parser_context_t * context_p,uint16_t opcode)164 parser_emit_ident_reference (parser_context_t *context_p, /**< context */
165                              uint16_t opcode) /* opcode */
166 {
167   if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
168   {
169     context_p->last_cbc_opcode = opcode;
170     return;
171   }
172 
173   uint16_t literal_index;
174 
175   if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
176   {
177     context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
178     literal_index = context_p->last_cbc.value;
179   }
180   else if (context_p->last_cbc_opcode == CBC_PUSH_THIS_LITERAL)
181   {
182     context_p->last_cbc_opcode = CBC_PUSH_THIS;
183     literal_index = context_p->last_cbc.literal_index;
184   }
185   else
186   {
187     JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS);
188     context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
189     literal_index = context_p->last_cbc.third_literal_index;
190   }
191 
192   parser_emit_cbc_literal (context_p, opcode, literal_index);
193 } /* parser_emit_ident_reference */
194 
195 /**
196  * Generate byte code for operators with lvalue.
197  */
198 static void
parser_emit_unary_lvalue_opcode(parser_context_t * context_p,cbc_opcode_t opcode)199 parser_emit_unary_lvalue_opcode (parser_context_t *context_p, /**< context */
200                                  cbc_opcode_t opcode) /**< opcode */
201 {
202   if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode)
203       && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
204   {
205     parser_check_invalid_assign (context_p);
206 
207     uint16_t unary_opcode;
208 
209     if (opcode == CBC_DELETE_PUSH_RESULT)
210     {
211       if (JERRY_UNLIKELY (context_p->status_flags & PARSER_IS_STRICT))
212       {
213         parser_raise_error (context_p, PARSER_ERR_DELETE_IDENT_NOT_ALLOWED);
214       }
215 
216       unary_opcode = CBC_DELETE_IDENT_PUSH_RESULT;
217     }
218     else
219     {
220       JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, opcode + CBC_UNARY_LVALUE_WITH_IDENT));
221       unary_opcode = (uint16_t) (opcode + CBC_UNARY_LVALUE_WITH_IDENT);
222     }
223 
224     parser_emit_ident_reference (context_p, unary_opcode);
225 
226 #if ENABLED (JERRY_ES2015)
227     if (unary_opcode != CBC_DELETE_IDENT_PUSH_RESULT
228         && scanner_literal_is_const_reg (context_p, context_p->last_cbc.literal_index))
229     {
230       /* The current value must be read, but it cannot be changed. */
231       context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
232       parser_emit_cbc_ext (context_p, CBC_EXT_THROW_ASSIGN_CONST_ERROR);
233     }
234 #endif /* ENABLED (JERRY_ES2015) */
235     return;
236   }
237 
238   if (context_p->last_cbc_opcode == CBC_PUSH_PROP)
239   {
240     JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, opcode));
241     context_p->last_cbc_opcode = (uint16_t) opcode;
242     return;
243   }
244 
245   if (PARSER_IS_PUSH_PROP_LITERAL (context_p->last_cbc_opcode))
246   {
247     context_p->last_cbc_opcode = PARSER_PUSH_PROP_LITERAL_TO_PUSH_LITERAL (context_p->last_cbc_opcode);
248   }
249   else
250   {
251     /* Invalid LeftHandSide expression. */
252     if (opcode == CBC_DELETE_PUSH_RESULT)
253     {
254 #if ENABLED (JERRY_ES2015)
255       if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)
256           || context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
257       {
258         parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
259         parser_emit_cbc (context_p, CBC_POP);
260         return;
261       }
262 #endif /* ENABLED (JERRY_ES2015) */
263       parser_emit_cbc (context_p, CBC_POP);
264       parser_emit_cbc (context_p, CBC_PUSH_TRUE);
265       return;
266     }
267 
268 #if ENABLED (JERRY_ES2015)
269     parser_check_invalid_new_target (context_p, opcode);
270 #endif /* ENABLED (JERRY_ES2015) */
271 
272     parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
273   }
274 
275   parser_emit_cbc (context_p, (uint16_t) opcode);
276 } /* parser_emit_unary_lvalue_opcode */
277 
278 /**
279  * Parse array literal.
280  */
281 static void
parser_parse_array_literal(parser_context_t * context_p)282 parser_parse_array_literal (parser_context_t *context_p) /**< context */
283 {
284   uint32_t pushed_items = 0;
285   uint16_t opcode = (uint16_t) CBC_ARRAY_APPEND;
286 
287   JERRY_ASSERT (context_p->token.type == LEXER_LEFT_SQUARE);
288 
289   parser_emit_cbc (context_p, CBC_CREATE_ARRAY);
290   lexer_next_token (context_p);
291 
292   while (true)
293   {
294     if (context_p->token.type == LEXER_RIGHT_SQUARE)
295     {
296       if (pushed_items > 0)
297       {
298         parser_emit_cbc_call (context_p, opcode, pushed_items);
299       }
300       return;
301     }
302 
303     pushed_items++;
304 
305     if (context_p->token.type == LEXER_COMMA)
306     {
307       parser_emit_cbc (context_p, CBC_PUSH_ELISION);
308       lexer_next_token (context_p);
309     }
310     else
311     {
312 #if ENABLED (JERRY_ES2015)
313       if (context_p->token.type == LEXER_THREE_DOTS)
314       {
315         opcode = (uint16_t) (PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND));
316         pushed_items++;
317         lexer_next_token (context_p);
318         parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SPREAD_ELEMENT);
319       }
320 #endif /* ENABLED (JERRY_ES2015) */
321 
322       parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
323 
324       if (context_p->last_cbc_opcode == CBC_PUSH_THIS)
325       {
326         parser_flush_cbc (context_p);
327       }
328 
329       if (context_p->token.type == LEXER_COMMA)
330       {
331         lexer_next_token (context_p);
332       }
333       else if (context_p->token.type != LEXER_RIGHT_SQUARE)
334       {
335         parser_raise_error (context_p, PARSER_ERR_ARRAY_ITEM_SEPARATOR_EXPECTED);
336       }
337     }
338 
339     if (pushed_items >= 64)
340     {
341       parser_emit_cbc_call (context_p, opcode, pushed_items);
342 #if ENABLED (JERRY_ES2015)
343       opcode = (uint16_t) CBC_ARRAY_APPEND;
344 #endif /* ENABLED (JERRY_ES2015) */
345       pushed_items = 0;
346     }
347   }
348 } /* parser_parse_array_literal */
349 
350 #if !ENABLED (JERRY_ES2015)
351 /**
352  * Object literal item types.
353  */
354 typedef enum
355 {
356   PARSER_OBJECT_PROPERTY_START,                /**< marks the start of the property list */
357   PARSER_OBJECT_PROPERTY_VALUE,                /**< value property */
358   PARSER_OBJECT_PROPERTY_GETTER,               /**< getter property */
359   PARSER_OBJECT_PROPERTY_SETTER,               /**< setter property */
360   PARSER_OBJECT_PROPERTY_BOTH_ACCESSORS,       /**< both getter and setter properties are set */
361 } parser_object_literal_item_types_t;
362 
363 /**
364  * Parse object literal.
365  */
366 static void
parser_append_object_literal_item(parser_context_t * context_p,uint16_t item_index,parser_object_literal_item_types_t item_type)367 parser_append_object_literal_item (parser_context_t *context_p, /**< context */
368                                    uint16_t item_index, /**< index of the item name */
369                                    parser_object_literal_item_types_t item_type) /**< type of the item */
370 {
371   parser_stack_iterator_t iterator;
372   uint8_t *current_item_type_p;
373 
374   iterator.current_p = context_p->stack.first_p;
375   iterator.current_position = context_p->stack.last_position;
376 
377   while (true)
378   {
379     current_item_type_p = iterator.current_p->bytes + iterator.current_position - 1;
380 
381     if (*current_item_type_p == PARSER_OBJECT_PROPERTY_START)
382     {
383       parser_stack_push_uint16 (context_p, item_index);
384       parser_stack_push_uint8 (context_p, (uint8_t) item_type);
385       return;
386     }
387 
388     iterator.current_position--;
389     if (iterator.current_position == 0)
390     {
391       iterator.current_p = iterator.current_p->next_p;
392       iterator.current_position = PARSER_STACK_PAGE_SIZE;
393     }
394 
395     uint32_t current_item_index = iterator.current_p->bytes[iterator.current_position - 1];
396 
397     iterator.current_position--;
398     if (iterator.current_position == 0)
399     {
400       iterator.current_p = iterator.current_p->next_p;
401       iterator.current_position = PARSER_STACK_PAGE_SIZE;
402     }
403 
404     current_item_index |= ((uint32_t) iterator.current_p->bytes[iterator.current_position - 1]) << 8;
405 
406     iterator.current_position--;
407     if (iterator.current_position == 0)
408     {
409       iterator.current_p = iterator.current_p->next_p;
410       iterator.current_position = PARSER_STACK_PAGE_SIZE;
411     }
412 
413     if (current_item_index == item_index)
414     {
415       if (item_type == PARSER_OBJECT_PROPERTY_VALUE
416           && *current_item_type_p == PARSER_OBJECT_PROPERTY_VALUE
417           && !(context_p->status_flags & PARSER_IS_STRICT))
418       {
419         return;
420       }
421 
422       if (item_type == PARSER_OBJECT_PROPERTY_GETTER
423           && *current_item_type_p == PARSER_OBJECT_PROPERTY_SETTER)
424       {
425         break;
426       }
427 
428       if (item_type == PARSER_OBJECT_PROPERTY_SETTER
429           && *current_item_type_p == PARSER_OBJECT_PROPERTY_GETTER)
430       {
431         break;
432       }
433 
434       parser_raise_error (context_p, PARSER_ERR_OBJECT_PROPERTY_REDEFINED);
435     }
436   }
437 
438   uint8_t *last_page_p = context_p->stack.first_p->bytes;
439 
440   *current_item_type_p = PARSER_OBJECT_PROPERTY_BOTH_ACCESSORS;
441 
442   if (current_item_type_p == (last_page_p + context_p->stack.last_position - 1))
443   {
444     context_p->stack_top_uint8 = PARSER_OBJECT_PROPERTY_BOTH_ACCESSORS;
445   }
446 } /* parser_append_object_literal_item */
447 #endif /* !ENABLED (JERRY_ES2015) */
448 
449 #if ENABLED (JERRY_ES2015)
450 /** Forward definition of parse array initializer. */
451 static void
452 parser_parse_array_initializer (parser_context_t *context_p, parser_pattern_flags_t flags);
453 
454 /** Forward definition of parse object initializer. */
455 static void
456 parser_parse_object_initializer (parser_context_t *context_p, parser_pattern_flags_t flags);
457 
458 /**
459  * Description of "get" literal string.
460  */
461 static const lexer_lit_location_t lexer_get_literal =
462 {
463   (const uint8_t *) "get", 3, LEXER_STRING_LITERAL, false
464 };
465 
466 /**
467  * Description of "set" literal string.
468  */
469 static const lexer_lit_location_t lexer_set_literal =
470 {
471   (const uint8_t *) "set", 3, LEXER_STRING_LITERAL, false
472 };
473 
474 /**
475  * Class literal parsing options.
476  */
477 typedef enum
478 {
479   PARSER_CLASS_LITERAL_NO_OPTS = 0,                   /**< no options are provided */
480   PARSER_CLASS_LITERAL_CTOR_PRESENT = (1 << 0),       /**< class constructor is present */
481   PARSER_CLASS_LITERAL_HERTIAGE_PRESENT = (1 << 1),   /**< class heritage is present */
482 } parser_class_literal_opts_t;
483 
484 /**
485  * Parse class literal.
486  */
487 static void
parser_parse_class_literal(parser_context_t * context_p,parser_class_literal_opts_t opts)488 parser_parse_class_literal (parser_context_t *context_p, /**< context */
489                             parser_class_literal_opts_t opts) /**< class literal parsing options */
490 {
491   JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
492 
493   uint32_t status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER;
494 
495   lexer_literal_t *ctor_literal_p = NULL;
496 
497   if (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT)
498   {
499     if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
500     {
501       parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
502     }
503 
504     ctor_literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
505     ctor_literal_p->type = LEXER_UNUSED_LITERAL;
506     ctor_literal_p->status_flags = 0;
507     parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, (uint16_t) (context_p->literal_count++));
508   }
509   else if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT)
510   {
511     parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE);
512   }
513   else
514   {
515     parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR);
516   }
517 
518   parser_emit_cbc_ext (context_p, CBC_EXT_INIT_CLASS);
519 
520   bool is_static = false;
521 
522   while (true)
523   {
524     if (!is_static)
525     {
526       lexer_skip_empty_statements (context_p);
527     }
528 
529     lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_CLASS_METHOD);
530 
531     if (context_p->token.type == LEXER_RIGHT_BRACE)
532     {
533       break;
534     }
535 
536     bool is_computed = false;
537 
538     if (context_p->token.type == LEXER_PROPERTY_GETTER || context_p->token.type == LEXER_PROPERTY_SETTER)
539     {
540       uint16_t literal_index, function_literal_index;
541       bool is_getter = (context_p->token.type == LEXER_PROPERTY_GETTER);
542 
543       if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
544       {
545         lexer_construct_literal_object (context_p,
546                                         (is_getter ? (lexer_lit_location_t *) &lexer_get_literal
547                                                    : (lexer_lit_location_t *) &lexer_set_literal),
548                                         LEXER_STRING_LITERAL);
549         goto parse_class_method;
550       }
551 
552       uint32_t accessor_status_flags = status_flags;
553       accessor_status_flags |= (is_getter ? PARSER_IS_PROPERTY_GETTER : PARSER_IS_PROPERTY_SETTER);
554 
555       lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_CLASS_METHOD | LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
556       literal_index = context_p->lit_object.index;
557 
558       if (context_p->token.type == LEXER_RIGHT_SQUARE)
559       {
560         is_computed = true;
561       }
562       else if (!is_static
563                && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
564                && lexer_compare_literal_to_string (context_p, "constructor", 11))
565       {
566         parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR);
567       }
568 
569       function_literal_index = lexer_construct_function_object (context_p, accessor_status_flags);
570 
571       parser_emit_cbc_literal (context_p,
572                                CBC_PUSH_LITERAL,
573                                literal_index);
574 
575       JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
576 
577       cbc_ext_opcode_t opcode;
578 
579       if (is_computed)
580       {
581         context_p->last_cbc.literal_index = function_literal_index;
582 
583         if (is_getter)
584         {
585           opcode = is_static ? CBC_EXT_SET_STATIC_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_GETTER;
586         }
587         else
588         {
589           opcode = is_static ? CBC_EXT_SET_STATIC_COMPUTED_SETTER : CBC_EXT_SET_COMPUTED_SETTER;
590         }
591       }
592       else
593       {
594         context_p->last_cbc.value = function_literal_index;
595 
596         if (is_getter)
597         {
598           opcode = is_static ? CBC_EXT_SET_STATIC_GETTER : CBC_EXT_SET_GETTER;
599         }
600         else
601         {
602           opcode = is_static ? CBC_EXT_SET_STATIC_SETTER : CBC_EXT_SET_SETTER;
603         }
604       }
605 
606       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode);
607       is_static = false;
608       continue;
609     }
610 
611     if (!is_static)
612     {
613       if (context_p->token.type == LEXER_KEYW_STATIC)
614       {
615         is_static = true;
616         continue;
617       }
618 
619       if (context_p->token.type == LEXER_CLASS_CONSTRUCTOR)
620       {
621         JERRY_ASSERT (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT);
622         JERRY_ASSERT (ctor_literal_p != NULL);
623 
624         if (ctor_literal_p->type == LEXER_FUNCTION_LITERAL)
625         {
626           /* 14.5.1 */
627           parser_raise_error (context_p, PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS);
628         }
629 
630         uint32_t constructor_status_flags = (status_flags
631                                              | PARSER_CLASS_CONSTRUCTOR
632                                              | PARSER_LEXICAL_ENV_NEEDED);
633 
634         if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT)
635         {
636           constructor_status_flags |= PARSER_ALLOW_SUPER_CALL;
637         }
638 
639         parser_flush_cbc (context_p);
640         ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, constructor_status_flags);
641         ctor_literal_p->u.bytecode_p = compiled_code_p;
642         ctor_literal_p->type = LEXER_FUNCTION_LITERAL;
643         continue;
644       }
645     }
646 
647     status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION
648                                  | PARSER_IS_ASYNC_FUNCTION
649                                  | PARSER_DISALLOW_AWAIT_YIELD);
650 
651     if (context_p->token.type == LEXER_KEYW_ASYNC)
652     {
653       status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
654 
655       if (!lexer_consume_generator (context_p))
656       {
657         lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
658       }
659     }
660 
661     if (context_p->token.type == LEXER_MULTIPLY)
662     {
663       lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
664       status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
665     }
666 
667     if (context_p->token.type == LEXER_RIGHT_SQUARE)
668     {
669       is_computed = true;
670     }
671     else if (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type))
672     {
673       if (is_static)
674       {
675         if (lexer_compare_literal_to_string (context_p, "prototype", 9))
676         {
677           parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE);
678         }
679       }
680       else if ((status_flags & PARSER_IS_GENERATOR_FUNCTION)
681                && lexer_compare_literal_to_string (context_p, "constructor", 11))
682       {
683         parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_GENERATOR);
684       }
685     }
686 
687 parse_class_method:
688     ; /* Empty statement to make compiler happy. */
689     uint16_t literal_index = context_p->lit_object.index;
690     uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags);
691 
692     parser_emit_cbc_literal (context_p,
693                              CBC_PUSH_LITERAL,
694                              function_literal_index);
695 
696     JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
697 
698     context_p->last_cbc.value = literal_index;
699 
700     if (is_static)
701     {
702       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (is_computed ? CBC_EXT_SET_STATIC_COMPUTED_PROPERTY_LITERAL
703                                                                      : CBC_EXT_SET_STATIC_PROPERTY_LITERAL);
704       is_static = false;
705     }
706     else
707     {
708       context_p->last_cbc_opcode = (is_computed ? PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL)
709                                                 : CBC_SET_LITERAL_PROPERTY);
710     }
711   }
712 } /* parser_parse_class_literal */
713 
714 /**
715  * Parse class statement or expression.
716  */
717 void
parser_parse_class(parser_context_t * context_p,bool is_statement)718 parser_parse_class (parser_context_t *context_p, /**< context */
719                     bool is_statement) /**< true - if class is parsed as a statement
720                                         *   false - otherwise (as an expression) */
721 {
722   JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);
723 
724   uint16_t class_ident_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
725   uint16_t class_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
726   parser_class_literal_opts_t opts = PARSER_CLASS_LITERAL_NO_OPTS;
727 
728   if (context_p->next_scanner_info_p->source_p == context_p->source_p)
729   {
730     JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR);
731     scanner_release_next (context_p, sizeof (scanner_info_t));
732     opts |= PARSER_CLASS_LITERAL_CTOR_PRESENT;
733   }
734 
735   if (is_statement)
736   {
737     /* Class statement must contain an identifier. */
738     lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL);
739     JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
740                   && context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
741 
742     if (context_p->next_scanner_info_p->source_p == context_p->source_p)
743     {
744       JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
745       parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
746     }
747     class_ident_index = context_p->lit_object.index;
748 
749     lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
750     class_name_index = context_p->lit_object.index;
751 
752 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
753     parser_module_append_export_name (context_p);
754     context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT);
755 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
756 
757     lexer_next_token (context_p);
758   }
759   else
760   {
761     lexer_next_token (context_p);
762 
763     /* Class expression may contain an identifier. */
764     if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
765     {
766       /* NOTE: If 'Function.name' will be supported, the current literal object must be set to 'name' property. */
767       lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
768       class_name_index = context_p->lit_object.index;
769       lexer_next_token (context_p);
770     }
771   }
772 
773   if (class_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS)
774   {
775     parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_NAMED_CLASS_ENV, class_name_index);
776   }
777   else
778   {
779     parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_ANONYMOUS_CLASS_ENV);
780   }
781 
782   bool is_strict = (context_p->status_flags & PARSER_IS_STRICT) != 0;
783 
784   /* 14.5. A ClassBody is always strict code. */
785   context_p->status_flags |= PARSER_IS_STRICT;
786 
787   if (context_p->token.type == LEXER_KEYW_EXTENDS)
788   {
789     lexer_next_token (context_p);
790     parser_parse_expression (context_p, PARSE_EXPR | PARSE_EXPR_LEFT_HAND_SIDE);
791     opts |= PARSER_CLASS_LITERAL_HERTIAGE_PRESENT;
792   }
793   else
794   {
795     /* Elisions represents that the classHeritage is not present */
796     parser_emit_cbc (context_p, CBC_PUSH_ELISION);
797   }
798 
799   if (context_p->token.type != LEXER_LEFT_BRACE)
800   {
801     parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
802   }
803 
804   /* ClassDeclaration is parsed. Continue with class body. */
805   parser_parse_class_literal (context_p, opts);
806 
807   if (class_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS)
808   {
809     parser_emit_cbc_ext_literal (context_p, CBC_EXT_FINALIZE_NAMED_CLASS, class_name_index);
810   }
811   else
812   {
813     parser_emit_cbc_ext (context_p, CBC_EXT_FINALIZE_ANONYMOUS_CLASS);
814   }
815 
816   if (is_statement)
817   {
818     cbc_opcode_t opcode = CBC_MOV_IDENT;
819 
820     if (class_ident_index < PARSER_REGISTER_START)
821     {
822       opcode = (scanner_literal_is_created (context_p, class_ident_index) ? CBC_ASSIGN_LET_CONST
823                                                                           : CBC_INIT_LET);
824     }
825 
826     parser_emit_cbc_literal (context_p, (uint16_t) opcode, class_ident_index);
827   }
828 
829   parser_flush_cbc (context_p);
830 
831   if (!is_strict)
832   {
833     /* Restore flag */
834     context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT;
835   }
836   context_p->status_flags &= (uint32_t) ~PARSER_ALLOW_SUPER;
837 
838   lexer_next_token (context_p);
839 } /* parser_parse_class */
840 #endif /* ENABLED (JERRY_ES2015) */
841 
842 #if ENABLED (JERRY_ES2015)
843 /**
844  * Parse object initializer method definition.
845  *
846  * See also: ES2015 14.3
847  */
848 static void
parser_parse_object_method(parser_context_t * context_p)849 parser_parse_object_method (parser_context_t *context_p) /**< context */
850 {
851   context_p->source_p--;
852   context_p->column--;
853   uint16_t function_literal_index = lexer_construct_function_object (context_p, PARSER_FUNCTION_CLOSURE);
854 
855   parser_emit_cbc_literal (context_p,
856                            CBC_PUSH_LITERAL,
857                            function_literal_index);
858 
859   lexer_next_token (context_p);
860 } /* parser_parse_object_method */
861 
862 /**
863  * Reparse the current literal as a common identifier.
864  */
865 static void
parser_reparse_as_common_identifier(parser_context_t * context_p,parser_line_counter_t start_line,parser_line_counter_t start_column)866 parser_reparse_as_common_identifier (parser_context_t *context_p, /**< context */
867                                      parser_line_counter_t start_line, /**< start line */
868                                      parser_line_counter_t start_column) /**< start column */
869 {
870   /* context_p->token.lit_location.char_p is showing the character after the string start,
871      so it is not suitable for reparsing as identifier.
872      e.g.: { 'foo' } */
873   if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
874   {
875     parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
876   }
877 
878   context_p->source_p = context_p->token.lit_location.char_p;
879   context_p->line = start_line;
880   context_p->column = start_column;
881 
882   lexer_next_token (context_p);
883 
884   if (context_p->token.type != LEXER_LITERAL)
885   {
886     parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
887   }
888 
889   JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
890 
891   lexer_construct_literal_object (context_p,
892                                   &context_p->token.lit_location,
893                                   LEXER_IDENT_LITERAL);
894 
895 } /* parser_reparse_as_common_identifier */
896 #endif /* ENABLED (JERRY_ES2015) */
897 
898 /**
899  * Parse object literal.
900  */
901 static void
parser_parse_object_literal(parser_context_t * context_p)902 parser_parse_object_literal (parser_context_t *context_p) /**< context */
903 {
904   JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
905 
906   parser_emit_cbc (context_p, CBC_CREATE_OBJECT);
907 
908 #if !ENABLED (JERRY_ES2015)
909   parser_stack_push_uint8 (context_p, PARSER_OBJECT_PROPERTY_START);
910 #endif /* !ENABLED (JERRY_ES2015) */
911 
912 #if ENABLED (JERRY_ES2015)
913   bool proto_seen = false;
914 #endif /* ENABLED (JERRY_ES2015) */
915 
916   while (true)
917   {
918     lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_NO_OPTS);
919 
920     switch (context_p->token.type)
921     {
922       case LEXER_RIGHT_BRACE:
923       {
924         break;
925       }
926       case LEXER_PROPERTY_GETTER:
927       case LEXER_PROPERTY_SETTER:
928       {
929         uint32_t status_flags;
930         cbc_ext_opcode_t opcode;
931 #if !ENABLED (JERRY_ES2015)
932         parser_object_literal_item_types_t item_type;
933 #endif /* !ENABLED (JERRY_ES2015) */
934 
935         if (context_p->token.type == LEXER_PROPERTY_GETTER)
936         {
937           status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_GETTER;
938           opcode = CBC_EXT_SET_GETTER;
939 #if !ENABLED (JERRY_ES2015)
940           item_type = PARSER_OBJECT_PROPERTY_GETTER;
941 #endif /* !ENABLED (JERRY_ES2015) */
942         }
943         else
944         {
945           status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_SETTER;
946           opcode = CBC_EXT_SET_SETTER;
947 #if !ENABLED (JERRY_ES2015)
948           item_type = PARSER_OBJECT_PROPERTY_SETTER;
949 #endif /* !ENABLED (JERRY_ES2015) */
950         }
951 
952         lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
953 
954         /* This assignment is a nop for computed getters/setters. */
955         uint16_t literal_index = context_p->lit_object.index;
956 
957 #if ENABLED (JERRY_ES2015)
958         if (context_p->token.type == LEXER_RIGHT_SQUARE)
959         {
960           opcode = ((opcode == CBC_EXT_SET_GETTER) ? CBC_EXT_SET_COMPUTED_GETTER
961                                                    : CBC_EXT_SET_COMPUTED_SETTER);
962         }
963 #else /* !ENABLED (JERRY_ES2015) */
964         parser_append_object_literal_item (context_p, literal_index, item_type);
965 #endif /* ENABLED (JERRY_ES2015) */
966 
967         uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags);
968 
969 #if ENABLED (JERRY_ES2015)
970         if (opcode >= CBC_EXT_SET_COMPUTED_GETTER)
971         {
972           literal_index = function_literal_index;
973         }
974 #endif /* ENABLED (JERRY_ES2015) */
975 
976         parser_emit_cbc_literal (context_p,
977                                  CBC_PUSH_LITERAL,
978                                  literal_index);
979 
980         JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
981         context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode);
982         context_p->last_cbc.value = function_literal_index;
983 
984         lexer_next_token (context_p);
985         break;
986       }
987 #if ENABLED (JERRY_ES2015)
988       case LEXER_RIGHT_SQUARE:
989       {
990         lexer_next_token (context_p);
991 
992         if (context_p->token.type == LEXER_LEFT_PAREN)
993         {
994           parser_parse_object_method (context_p);
995 
996           JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
997           context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL);
998           break;
999         }
1000 
1001         if (context_p->token.type != LEXER_COLON)
1002         {
1003           parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
1004         }
1005 
1006         lexer_next_token (context_p);
1007         parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
1008 
1009         if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1010         {
1011           context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL);
1012         }
1013         else
1014         {
1015           parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_PROPERTY);
1016         }
1017         break;
1018       }
1019       case LEXER_KEYW_ASYNC:
1020       case LEXER_MULTIPLY:
1021       {
1022         uint32_t status_flags = PARSER_FUNCTION_CLOSURE;
1023 
1024         if (context_p->token.type == LEXER_KEYW_ASYNC)
1025         {
1026           status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
1027           lexer_consume_generator (context_p);
1028         }
1029 
1030         if (context_p->token.type == LEXER_MULTIPLY)
1031         {
1032           status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
1033         }
1034 
1035         lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
1036 
1037         uint16_t opcode = CBC_SET_LITERAL_PROPERTY;
1038         /* This assignment is a nop for CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL. */
1039         uint16_t literal_index = context_p->lit_object.index;
1040 
1041         if (context_p->token.type == LEXER_RIGHT_SQUARE)
1042         {
1043           opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL);
1044         }
1045 
1046         uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags);
1047 
1048         parser_emit_cbc_literal (context_p,
1049                                  CBC_PUSH_LITERAL,
1050                                  function_literal_index);
1051 
1052         JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
1053         context_p->last_cbc_opcode = opcode;
1054         context_p->last_cbc.value = literal_index;
1055 
1056         lexer_next_token (context_p);
1057         break;
1058       }
1059 #endif /* ENABLED (JERRY_ES2015) */
1060       default:
1061       {
1062 #if ENABLED (JERRY_ES2015)
1063         const lexer_lit_location_t *literal_p = (const lexer_lit_location_t *) context_p->lit_object.literal_p;
1064         bool is_proto = ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL
1065                           || context_p->token.lit_location.type == LEXER_STRING_LITERAL)
1066                          && lexer_compare_identifier_to_string (literal_p, (uint8_t *) "__proto__", 9)
1067                          && lexer_check_next_character (context_p, LIT_CHAR_COLON));
1068         if (is_proto)
1069         {
1070           if (proto_seen)
1071           {
1072             parser_raise_error (context_p, PARSER_ERR_DUPLICATED_PROTO);
1073           }
1074 
1075           proto_seen = true;
1076         }
1077 #endif /* ENABLED (JERRY_ES2015) */
1078 
1079         uint16_t literal_index = context_p->lit_object.index;
1080 
1081 #if ENABLED (JERRY_ES2015)
1082         parser_line_counter_t start_line = context_p->token.line;
1083         parser_line_counter_t start_column = context_p->token.column;
1084 #else /* !ENABLED (JERRY_ES2015) */
1085         parser_append_object_literal_item (context_p,
1086                                            literal_index,
1087                                            PARSER_OBJECT_PROPERTY_VALUE);
1088 #endif /* ENABLED (JERRY_ES2015) */
1089 
1090         lexer_next_token (context_p);
1091 
1092 #if ENABLED (JERRY_ES2015)
1093         if (context_p->token.type == LEXER_LEFT_PAREN && !is_proto)
1094         {
1095           parser_parse_object_method (context_p);
1096 
1097           JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
1098           context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
1099           context_p->last_cbc.value = literal_index;
1100           break;
1101         }
1102 
1103         if ((context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_COMMA)
1104             && !is_proto)
1105         {
1106           parser_reparse_as_common_identifier (context_p, start_line, start_column);
1107           parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
1108 
1109           context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
1110           context_p->last_cbc.value = literal_index;
1111 
1112           lexer_next_token (context_p);
1113           break;
1114         }
1115 #endif /* ENABLED (JERRY_ES2015) */
1116 
1117         if (context_p->token.type != LEXER_COLON)
1118         {
1119           parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
1120         }
1121 
1122         lexer_next_token (context_p);
1123         parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
1124 
1125 #if ENABLED (JERRY_ES2015)
1126         if (is_proto)
1127         {
1128           parser_emit_cbc_ext (context_p, CBC_EXT_SET__PROTO__);
1129           break;
1130         }
1131 #endif /* ENABLED (JERRY_ES2015) */
1132 
1133         if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1134         {
1135           context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
1136           context_p->last_cbc.value = literal_index;
1137         }
1138         else
1139         {
1140           parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index);
1141         }
1142 
1143         break;
1144       }
1145     }
1146 
1147     if (context_p->token.type == LEXER_RIGHT_BRACE)
1148     {
1149       break;
1150     }
1151     else if (context_p->token.type != LEXER_COMMA)
1152     {
1153       parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
1154     }
1155   }
1156 
1157 #if !ENABLED (JERRY_ES2015)
1158   while (context_p->stack_top_uint8 != PARSER_OBJECT_PROPERTY_START)
1159   {
1160     parser_stack_pop (context_p, NULL, 3);
1161   }
1162 
1163   parser_stack_pop_uint8 (context_p);
1164 #endif /* !ENABLED (JERRY_ES2015) */
1165 } /* parser_parse_object_literal */
1166 
1167 /**
1168  * Parse function literal.
1169  */
1170 static void
parser_parse_function_expression(parser_context_t * context_p,uint32_t status_flags)1171 parser_parse_function_expression (parser_context_t *context_p, /**< context */
1172                                   uint32_t status_flags) /**< function status flags */
1173 {
1174   int literals = 0;
1175   uint16_t literal1 = 0;
1176   uint16_t literal2 = 0;
1177   uint16_t function_literal_index;
1178   int32_t function_name_index = -1;
1179 
1180 #if !ENABLED (JERRY_ES2015)
1181   JERRY_ASSERT (status_flags & PARSER_IS_FUNC_EXPRESSION);
1182 #endif /* !ENABLED (JERRY_ES2015) */
1183 
1184 #if ENABLED (JERRY_ES2015)
1185   if (status_flags & PARSER_IS_FUNC_EXPRESSION)
1186   {
1187 #endif /* !ENABLED (JERRY_ES2015) */
1188 
1189 #if ENABLED (JERRY_DEBUGGER)
1190     parser_line_counter_t debugger_line = context_p->token.line;
1191     parser_line_counter_t debugger_column = context_p->token.column;
1192 #endif /* ENABLED (JERRY_DEBUGGER) */
1193 
1194 #if ENABLED (JERRY_ES2015)
1195     uint32_t parent_status_flags = context_p->status_flags;
1196 
1197     context_p->status_flags &= (uint32_t) ~(PARSER_IS_ASYNC_FUNCTION
1198                                             | PARSER_IS_GENERATOR_FUNCTION
1199                                             | PARSER_DISALLOW_AWAIT_YIELD);
1200 
1201     if (status_flags & PARSER_IS_ASYNC_FUNCTION)
1202     {
1203       /* The name of the function cannot be await. */
1204       context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
1205     }
1206 
1207     if (lexer_consume_generator (context_p))
1208     {
1209       /* The name of the function cannot be yield. */
1210       context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
1211       status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
1212     }
1213 #endif /* ENABLED (JERRY_ES2015) */
1214 
1215     if (!lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
1216     {
1217       lexer_next_token (context_p);
1218 
1219       if (context_p->token.type != LEXER_LITERAL
1220           || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1221       {
1222         parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
1223       }
1224 
1225       parser_flush_cbc (context_p);
1226 
1227       lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
1228 
1229 #if ENABLED (JERRY_DEBUGGER)
1230       if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
1231       {
1232         jerry_debugger_send_string (JERRY_DEBUGGER_FUNCTION_NAME,
1233                                     JERRY_DEBUGGER_NO_SUBTYPE,
1234                                     context_p->lit_object.literal_p->u.char_p,
1235                                     context_p->lit_object.literal_p->prop.length);
1236 
1237         /* Reset token position for the function. */
1238         context_p->token.line = debugger_line;
1239         context_p->token.column = debugger_column;
1240       }
1241 #endif /* ENABLED (JERRY_DEBUGGER) */
1242 
1243       if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS)
1244       {
1245         status_flags |= PARSER_HAS_NON_STRICT_ARG;
1246       }
1247 
1248       function_name_index = context_p->lit_object.index;
1249     }
1250 
1251 #if ENABLED (JERRY_ES2015)
1252     context_p->status_flags = parent_status_flags;
1253   }
1254 #endif /* ENABLED (JERRY_ES2015) */
1255 
1256   if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1257   {
1258     literals = 1;
1259     literal1 = context_p->last_cbc.literal_index;
1260     context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
1261   }
1262   else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
1263   {
1264     literals = 2;
1265     literal1 = context_p->last_cbc.literal_index;
1266     literal2 = context_p->last_cbc.value;
1267     context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
1268   }
1269 
1270   function_literal_index = lexer_construct_function_object (context_p, status_flags);
1271 
1272   JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
1273 
1274   if (literals == 1)
1275   {
1276     context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
1277     context_p->last_cbc.literal_index = literal1;
1278     context_p->last_cbc.value = function_literal_index;
1279   }
1280   else if (literals == 2)
1281   {
1282     context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS;
1283     context_p->last_cbc.literal_index = literal1;
1284     context_p->last_cbc.value = literal2;
1285     context_p->last_cbc.third_literal_index = function_literal_index;
1286   }
1287   else
1288   {
1289     parser_emit_cbc_literal (context_p,
1290                              CBC_PUSH_LITERAL,
1291                              function_literal_index);
1292 
1293     if (function_name_index != -1)
1294     {
1295       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION);
1296       context_p->last_cbc.value = (uint16_t) function_name_index;
1297     }
1298   }
1299 
1300   context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL;
1301   context_p->last_cbc.literal_keyword_type = LEXER_EOS;
1302 } /* parser_parse_function_expression */
1303 
1304 #if ENABLED (JERRY_ES2015)
1305 
1306 /**
1307  * Parse template literal.
1308  */
1309 static void
parser_parse_template_literal(parser_context_t * context_p)1310 parser_parse_template_literal (parser_context_t *context_p) /**< context */
1311 {
1312   bool is_empty_head = true;
1313 
1314   if (context_p->token.lit_location.length > 0)
1315   {
1316     is_empty_head = false;
1317 
1318     lexer_construct_literal_object (context_p,
1319                                     &context_p->token.lit_location,
1320                                     context_p->token.lit_location.type);
1321 
1322     parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
1323   }
1324 
1325   lexer_next_token (context_p);
1326   parser_parse_expression (context_p, PARSE_EXPR);
1327 
1328   if (context_p->token.type != LEXER_RIGHT_BRACE)
1329   {
1330     parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
1331   }
1332 
1333   if (!is_empty_head)
1334   {
1335     if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
1336     {
1337       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS);
1338     }
1339     else if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1340     {
1341       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL);
1342     }
1343     else
1344     {
1345       parser_emit_cbc_ext (context_p, CBC_EXT_STRING_CONCAT);
1346     }
1347   }
1348 
1349   context_p->source_p--;
1350   context_p->column--;
1351   lexer_parse_string (context_p, LEXER_STRING_NO_OPTS);
1352 
1353   if (is_empty_head || context_p->token.lit_location.length > 0)
1354   {
1355     lexer_construct_literal_object (context_p,
1356                                     &context_p->token.lit_location,
1357                                     context_p->token.lit_location.type);
1358 
1359     if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1360     {
1361       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS);
1362       context_p->last_cbc.value = context_p->lit_object.index;
1363       context_p->last_cbc.literal_type = context_p->token.lit_location.type;
1364       context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type;
1365     }
1366     else
1367     {
1368       parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_STRING_CONCAT_RIGHT_LITERAL);
1369     }
1370   }
1371 
1372   while (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
1373   {
1374     lexer_next_token (context_p);
1375 
1376     parser_parse_expression (context_p, PARSE_EXPR);
1377 
1378     if (context_p->token.type != LEXER_RIGHT_BRACE)
1379     {
1380       parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
1381     }
1382 
1383     if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1384     {
1385       context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL);
1386     }
1387     else
1388     {
1389       parser_emit_cbc_ext (context_p, CBC_EXT_STRING_CONCAT);
1390     }
1391 
1392     context_p->source_p--;
1393     context_p->column--;
1394     lexer_parse_string (context_p, LEXER_STRING_NO_OPTS);
1395 
1396     if (context_p->token.lit_location.length > 0)
1397     {
1398       lexer_construct_literal_object (context_p,
1399                                       &context_p->token.lit_location,
1400                                       context_p->token.lit_location.type);
1401 
1402       parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_STRING_CONCAT_RIGHT_LITERAL);
1403     }
1404   }
1405 } /* parser_parse_template_literal */
1406 
1407 /**
1408  * Parse tagged template literal.
1409  */
1410 static size_t
parser_parse_tagged_template_literal(parser_context_t * context_p)1411 parser_parse_tagged_template_literal (parser_context_t *context_p) /**< context */
1412 {
1413   JERRY_ASSERT (context_p->token.type == LEXER_TEMPLATE_LITERAL);
1414 
1415   uint32_t call_arguments = 0;
1416   ecma_collection_t *collection_p;
1417 
1418   if (context_p->tagged_template_literal_cp == JMEM_CP_NULL)
1419   {
1420     collection_p = ecma_new_collection ();
1421     ECMA_SET_INTERNAL_VALUE_POINTER (context_p->tagged_template_literal_cp, collection_p);
1422   }
1423   else
1424   {
1425     collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_p->tagged_template_literal_cp);
1426     if (collection_p->item_count > CBC_MAXIMUM_BYTE_VALUE)
1427     {
1428       parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
1429     }
1430   }
1431 
1432   const uint32_t tagged_id = collection_p->item_count;
1433   uint32_t prop_idx = 0;
1434   ecma_object_t *raw_strings_p;
1435   ecma_object_t *template_obj_p = parser_new_tagged_template_literal (&raw_strings_p);
1436   ecma_collection_push_back (collection_p, ecma_make_object_value (template_obj_p));
1437 
1438   parser_tagged_template_literal_append_strings (context_p, template_obj_p, raw_strings_p, prop_idx++);
1439 
1440   call_arguments++;
1441   parser_emit_cbc_ext_call (context_p, CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, tagged_id);
1442 
1443   while (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
1444   {
1445     JERRY_ASSERT (context_p->source_p[-1] == LIT_CHAR_LEFT_BRACE);
1446     lexer_next_token (context_p);
1447 
1448     if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE)
1449     {
1450       parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
1451     }
1452 
1453     parser_parse_expression (context_p, PARSE_EXPR);
1454 
1455     if (context_p->token.type != LEXER_RIGHT_BRACE)
1456     {
1457       parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
1458     }
1459 
1460     context_p->source_p--;
1461     context_p->column--;
1462     lexer_parse_string (context_p, LEXER_STRING_NO_OPTS);
1463 
1464     parser_tagged_template_literal_append_strings (context_p, template_obj_p, raw_strings_p, prop_idx++);
1465   }
1466 
1467   parser_tagged_template_literal_finalize (template_obj_p, raw_strings_p);
1468 
1469   return call_arguments;
1470 } /* parser_parse_tagged_template_literal */
1471 
1472 /**
1473  * Checks wheteher the current expression can be an assignment expression.
1474  *
1475  * @return true if the current expression can be an assignment expression, false otherwise
1476  */
1477 static inline bool JERRY_ATTR_ALWAYS_INLINE
parser_is_assignment_expr(parser_context_t * context_p)1478 parser_is_assignment_expr (parser_context_t *context_p)
1479 {
1480   return (context_p->stack_top_uint8 == LEXER_EXPRESSION_START
1481           || context_p->stack_top_uint8 == LEXER_LEFT_PAREN
1482           || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST
1483           || LEXER_IS_BINARY_LVALUE_TOKEN (context_p->stack_top_uint8));
1484 } /* parser_is_assignment_expr */
1485 
1486 /**
1487  * Throws an error if the current expression is not an assignment expression.
1488  */
1489 static inline void JERRY_ATTR_ALWAYS_INLINE
parser_check_assignment_expr(parser_context_t * context_p)1490 parser_check_assignment_expr (parser_context_t *context_p)
1491 {
1492   if (!parser_is_assignment_expr (context_p))
1493   {
1494     parser_raise_error (context_p, PARSER_ERR_ASSIGNMENT_EXPECTED);
1495   }
1496 } /* parser_check_assignment_expr */
1497 
1498 /**
1499  * Checks whether the next token is a valid continuation token after an AssignmentExpression.
1500  */
1501 static inline bool JERRY_ATTR_ALWAYS_INLINE
parser_abort_parsing_after_assignment_expression(parser_context_t * context_p)1502 parser_abort_parsing_after_assignment_expression (parser_context_t *context_p)
1503 {
1504   return (context_p->token.type != LEXER_RIGHT_PAREN
1505           && context_p->token.type != LEXER_COMMA);
1506 } /* parser_abort_parsing_after_assignment_expression */
1507 
1508 #endif /* ENABLED (JERRY_ES2015) */
1509 
1510 /**
1511  * Parse and record unary operators, and parse the primary literal.
1512  *
1513  * @return true if parsing should be aborted, true otherwise
1514  */
1515 static bool
parser_parse_unary_expression(parser_context_t * context_p,size_t * grouping_level_p)1516 parser_parse_unary_expression (parser_context_t *context_p, /**< context */
1517                                size_t *grouping_level_p) /**< grouping level */
1518 {
1519   bool new_was_seen = false;
1520 
1521   /* Collect unary operators. */
1522   while (true)
1523   {
1524     /* Convert plus and minus binary operators to unary operators. */
1525     switch (context_p->token.type)
1526     {
1527       case LEXER_ADD:
1528       {
1529         context_p->token.type = LEXER_PLUS;
1530         break;
1531       }
1532       case LEXER_SUBTRACT:
1533       {
1534         context_p->token.type = LEXER_NEGATE;
1535         break;
1536       }
1537 #if ENABLED (JERRY_ES2015)
1538       case LEXER_KEYW_AWAIT:
1539       {
1540         if (JERRY_UNLIKELY (context_p->token.lit_location.has_escape))
1541         {
1542           parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
1543         }
1544         break;
1545       }
1546 #endif /* ENABLED (JERRY_ES2015) */
1547     }
1548 
1549     /* Bracketed expressions are primary expressions. At this
1550      * point their left paren is pushed onto the stack and
1551      * they are processed when their closing paren is reached. */
1552     if (context_p->token.type == LEXER_LEFT_PAREN)
1553     {
1554 #if ENABLED (JERRY_ES2015)
1555       if (context_p->next_scanner_info_p->source_p == context_p->source_p)
1556       {
1557         JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
1558         break;
1559       }
1560 #endif /* ENABLED (JERRY_ES2015) */
1561       (*grouping_level_p) += PARSER_GROUPING_LEVEL_INCREASE;
1562       new_was_seen = false;
1563     }
1564     else if (context_p->token.type == LEXER_KEYW_NEW)
1565     {
1566       /* After 'new' unary operators are not allowed. */
1567       new_was_seen = true;
1568 
1569 #if ENABLED (JERRY_ES2015)
1570       /* Check if "new.target" is written here. */
1571       if (scanner_try_scan_new_target (context_p))
1572       {
1573         if (!(context_p->status_flags & PARSER_ALLOW_NEW_TARGET))
1574         {
1575           parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED);
1576         }
1577 
1578         parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_NEW_TARGET);
1579         lexer_next_token (context_p);
1580         /* Found "new.target" return here */
1581         return false;
1582       }
1583 #endif /* ENABLED (JERRY_ES2015) */
1584     }
1585     else if (new_was_seen
1586              || (*grouping_level_p == PARSE_EXPR_LEFT_HAND_SIDE)
1587              || !LEXER_IS_UNARY_OP_TOKEN (context_p->token.type))
1588     {
1589       break;
1590     }
1591 
1592     parser_stack_push_uint8 (context_p, context_p->token.type);
1593     lexer_next_token (context_p);
1594   }
1595 
1596   /* Parse primary expression. */
1597   switch (context_p->token.type)
1598   {
1599 #if ENABLED (JERRY_ES2015)
1600     case LEXER_TEMPLATE_LITERAL:
1601     {
1602       if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
1603       {
1604         parser_parse_template_literal (context_p);
1605         break;
1606       }
1607 
1608       /* The string is a normal string literal. */
1609       /* FALLTHRU */
1610     }
1611 #endif /* ENABLED (JERRY_ES2015) */
1612     case LEXER_LITERAL:
1613     {
1614 #if ENABLED (JERRY_ES2015)
1615       if (JERRY_UNLIKELY (context_p->next_scanner_info_p->source_p == context_p->source_p))
1616       {
1617         JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
1618 
1619         uint32_t arrow_status_flags = (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
1620 
1621         if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)
1622         {
1623           JERRY_ASSERT (lexer_token_is_async (context_p));
1624           JERRY_ASSERT (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT));
1625 
1626           uint32_t saved_status_flags = context_p->status_flags;
1627 
1628           context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
1629           lexer_next_token (context_p);
1630           context_p->status_flags = saved_status_flags;
1631 
1632           if (context_p->token.type == LEXER_KEYW_FUNCTION)
1633           {
1634             uint32_t status_flags = (PARSER_FUNCTION_CLOSURE
1635                                      | PARSER_IS_FUNC_EXPRESSION
1636                                      | PARSER_IS_ASYNC_FUNCTION
1637                                      | PARSER_DISALLOW_AWAIT_YIELD);
1638             parser_parse_function_expression (context_p, status_flags);
1639             break;
1640           }
1641 
1642           arrow_status_flags = (PARSER_IS_FUNCTION
1643                                 | PARSER_IS_ARROW_FUNCTION
1644                                 | PARSER_IS_ASYNC_FUNCTION
1645                                 | PARSER_DISALLOW_AWAIT_YIELD);
1646         }
1647 
1648         parser_check_assignment_expr (context_p);
1649         parser_parse_function_expression (context_p, arrow_status_flags);
1650         return parser_abort_parsing_after_assignment_expression (context_p);
1651       }
1652 #endif /* ENABLED (JERRY_ES2015) */
1653 
1654       uint8_t type = context_p->token.lit_location.type;
1655 
1656       if (type == LEXER_IDENT_LITERAL || type == LEXER_STRING_LITERAL)
1657       {
1658         lexer_construct_literal_object (context_p,
1659                                         &context_p->token.lit_location,
1660                                         context_p->token.lit_location.type);
1661 
1662 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1663         if ((context_p->status_flags & PARSER_MODULE_STORE_IDENT)
1664             && type == LEXER_IDENT_LITERAL)
1665         {
1666           context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
1667           context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT);
1668         }
1669 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1670       }
1671       else if (type == LEXER_NUMBER_LITERAL)
1672       {
1673         bool is_negative_number = false;
1674 
1675         if ((context_p->stack_top_uint8 == LEXER_PLUS || context_p->stack_top_uint8 == LEXER_NEGATE)
1676             && !lexer_check_post_primary_exp (context_p))
1677         {
1678           do
1679           {
1680             if (context_p->stack_top_uint8 == LEXER_NEGATE)
1681             {
1682               is_negative_number = !is_negative_number;
1683             }
1684             parser_stack_pop_uint8 (context_p);
1685           }
1686           while (context_p->stack_top_uint8 == LEXER_PLUS
1687                  || context_p->stack_top_uint8 == LEXER_NEGATE);
1688         }
1689 
1690         if (lexer_construct_number_object (context_p, true, is_negative_number))
1691         {
1692           JERRY_ASSERT (context_p->lit_object.index <= CBC_PUSH_NUMBER_BYTE_RANGE_END);
1693 
1694           parser_emit_cbc_push_number (context_p, is_negative_number);
1695           break;
1696         }
1697       }
1698 
1699       cbc_opcode_t opcode = CBC_PUSH_LITERAL;
1700 
1701       if (context_p->token.keyword_type != LEXER_KEYW_EVAL)
1702       {
1703         if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1704         {
1705           context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
1706           context_p->last_cbc.value = context_p->lit_object.index;
1707           context_p->last_cbc.literal_type = context_p->token.lit_location.type;
1708           context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type;
1709           break;
1710         }
1711 
1712         if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
1713         {
1714           context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS;
1715           context_p->last_cbc.third_literal_index = context_p->lit_object.index;
1716           context_p->last_cbc.literal_type = context_p->token.lit_location.type;
1717           context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type;
1718           break;
1719         }
1720 
1721         if (context_p->last_cbc_opcode == CBC_PUSH_THIS)
1722         {
1723           context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
1724           opcode = CBC_PUSH_THIS_LITERAL;
1725         }
1726       }
1727 
1728       parser_emit_cbc_literal_from_token (context_p, (uint16_t) opcode);
1729       break;
1730     }
1731     case LEXER_KEYW_FUNCTION:
1732     {
1733       parser_parse_function_expression (context_p, PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION);
1734       break;
1735     }
1736     case LEXER_LEFT_BRACE:
1737     {
1738 #if ENABLED (JERRY_ES2015)
1739       if (context_p->next_scanner_info_p->source_p == context_p->source_p)
1740       {
1741         JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
1742 
1743         if (parser_is_assignment_expr (context_p))
1744         {
1745           parser_parse_object_initializer (context_p, PARSER_PATTERN_NO_OPTS);
1746           return parser_abort_parsing_after_assignment_expression (context_p);
1747         }
1748 
1749         scanner_release_next (context_p, sizeof (scanner_location_info_t));
1750       }
1751 #endif /* ENABLED (JERRY_ES2015) */
1752 
1753       parser_parse_object_literal (context_p);
1754       break;
1755     }
1756     case LEXER_LEFT_SQUARE:
1757     {
1758 #if ENABLED (JERRY_ES2015)
1759       if (context_p->next_scanner_info_p->source_p == context_p->source_p)
1760       {
1761         JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
1762 
1763         if (parser_is_assignment_expr (context_p))
1764         {
1765           parser_parse_array_initializer (context_p, PARSER_PATTERN_NO_OPTS);
1766           return parser_abort_parsing_after_assignment_expression (context_p);
1767         }
1768 
1769         scanner_release_next (context_p, sizeof (scanner_location_info_t));
1770       }
1771 #endif /* ENABLED (JERRY_ES2015) */
1772 
1773       parser_parse_array_literal (context_p);
1774       break;
1775     }
1776     case LEXER_DIVIDE:
1777     case LEXER_ASSIGN_DIVIDE:
1778     {
1779       lexer_construct_regexp_object (context_p, false);
1780 
1781       uint16_t literal_index = (uint16_t) (context_p->literal_count - 1);
1782 
1783       if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1784       {
1785         context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
1786         context_p->last_cbc.value = literal_index;
1787       }
1788       else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
1789       {
1790         context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS;
1791         context_p->last_cbc.third_literal_index = literal_index;
1792       }
1793       else
1794       {
1795         parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index);
1796       }
1797 
1798       context_p->last_cbc.literal_type = LEXER_REGEXP_LITERAL;
1799       context_p->last_cbc.literal_keyword_type = LEXER_EOS;
1800       break;
1801     }
1802     case LEXER_KEYW_THIS:
1803     {
1804 #if ENABLED (JERRY_ES2015)
1805       if (context_p->status_flags & PARSER_ALLOW_SUPER_CALL)
1806       {
1807         parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_LEXICAL_THIS);
1808       }
1809       else
1810       {
1811 #endif /* ENABLED (JERRY_ES2015) */
1812         parser_emit_cbc (context_p, CBC_PUSH_THIS);
1813 #if ENABLED (JERRY_ES2015)
1814       }
1815 #endif /* ENABLED (JERRY_ES2015) */
1816       break;
1817     }
1818     case LEXER_LIT_TRUE:
1819     {
1820       parser_emit_cbc (context_p, CBC_PUSH_TRUE);
1821       break;
1822     }
1823     case LEXER_LIT_FALSE:
1824     {
1825       parser_emit_cbc (context_p, CBC_PUSH_FALSE);
1826       break;
1827     }
1828     case LEXER_LIT_NULL:
1829     {
1830       parser_emit_cbc (context_p, CBC_PUSH_NULL);
1831       break;
1832     }
1833 #if ENABLED (JERRY_ES2015)
1834     case LEXER_KEYW_CLASS:
1835     {
1836       parser_parse_class (context_p, false);
1837       return false;
1838     }
1839     case LEXER_KEYW_SUPER:
1840     {
1841       if (context_p->status_flags & PARSER_ALLOW_SUPER)
1842       {
1843         if (lexer_check_next_characters (context_p, LIT_CHAR_DOT, LIT_CHAR_LEFT_SQUARE))
1844         {
1845           parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER);
1846           break;
1847         }
1848 
1849         if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)
1850             && (context_p->status_flags & PARSER_ALLOW_SUPER_CALL))
1851         {
1852           parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER_CONSTRUCTOR);
1853           break;
1854         }
1855       }
1856 
1857       parser_raise_error (context_p, PARSER_ERR_UNEXPECTED_SUPER_KEYWORD);
1858     }
1859     case LEXER_LEFT_PAREN:
1860     {
1861       JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p
1862                     && context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
1863 
1864       parser_check_assignment_expr (context_p);
1865 
1866       parser_parse_function_expression (context_p, PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
1867       return parser_abort_parsing_after_assignment_expression (context_p);
1868     }
1869     case LEXER_KEYW_YIELD:
1870     {
1871       JERRY_ASSERT ((context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1872                     && !(context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD));
1873 
1874       if (context_p->token.lit_location.has_escape)
1875       {
1876         parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
1877       }
1878 
1879       parser_check_assignment_expr (context_p);
1880       lexer_next_token (context_p);
1881 
1882       cbc_ext_opcode_t opcode = CBC_EXT_YIELD;
1883 
1884       if (!lexer_check_yield_no_arg (context_p))
1885       {
1886         if (context_p->token.type == LEXER_MULTIPLY)
1887         {
1888           lexer_next_token (context_p);
1889           opcode = CBC_EXT_YIELD_ITERATOR;
1890         }
1891 
1892         parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
1893       }
1894       else
1895       {
1896         parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
1897       }
1898 
1899       parser_emit_cbc_ext (context_p, opcode);
1900 
1901       return (context_p->token.type != LEXER_RIGHT_PAREN
1902               && context_p->token.type != LEXER_COMMA);
1903     }
1904 #endif /* ENABLED (JERRY_ES2015) */
1905     default:
1906     {
1907       bool is_left_hand_side = (*grouping_level_p == PARSE_EXPR_LEFT_HAND_SIDE);
1908       parser_raise_error (context_p, (is_left_hand_side ? PARSER_ERR_LEFT_HAND_SIDE_EXP_EXPECTED
1909                                                         : PARSER_ERR_PRIMARY_EXP_EXPECTED));
1910       break;
1911     }
1912   }
1913   lexer_next_token (context_p);
1914   return false;
1915 } /* parser_parse_unary_expression */
1916 
1917 /**
1918  * Parse the postfix part of unary operators, and
1919  * generate byte code for the whole expression.
1920  */
1921 static void
parser_process_unary_expression(parser_context_t * context_p,size_t grouping_level)1922 parser_process_unary_expression (parser_context_t *context_p, /**< context */
1923                                  size_t grouping_level) /**< grouping level */
1924 {
1925   /* Parse postfix part of a primary expression. */
1926   while (true)
1927   {
1928     /* Since break would only break the switch, we use
1929      * continue to continue this loop. Without continue,
1930      * the code abandons the loop. */
1931     switch (context_p->token.type)
1932     {
1933       case LEXER_DOT:
1934       {
1935         parser_push_result (context_p);
1936 
1937         lexer_expect_identifier (context_p, LEXER_STRING_LITERAL);
1938         JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
1939                       && context_p->lit_object.literal_p->type == LEXER_STRING_LITERAL);
1940         context_p->token.lit_location.type = LEXER_STRING_LITERAL;
1941 
1942         if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
1943         {
1944           JERRY_ASSERT (CBC_ARGS_EQ (CBC_PUSH_PROP_LITERAL_LITERAL,
1945                                      CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2));
1946           context_p->last_cbc_opcode = CBC_PUSH_PROP_LITERAL_LITERAL;
1947           context_p->last_cbc.value = context_p->lit_object.index;
1948         }
1949         else if (context_p->last_cbc_opcode == CBC_PUSH_THIS)
1950         {
1951           context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
1952           parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_PROP_THIS_LITERAL);
1953         }
1954 #if ENABLED (JERRY_ES2015)
1955         else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER))
1956         {
1957           context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL);
1958           context_p->last_cbc.literal_index = context_p->lit_object.index;
1959         }
1960 #endif /* ENABLED (JERRY_ES2015) */
1961         else
1962         {
1963           parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_PROP_LITERAL);
1964         }
1965         lexer_next_token (context_p);
1966         continue;
1967       }
1968 
1969       case LEXER_LEFT_SQUARE:
1970       {
1971         parser_push_result (context_p);
1972 
1973 #if ENABLED (JERRY_ES2015)
1974         uint16_t last_cbc_opcode = context_p->last_cbc_opcode;
1975 
1976         if (last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER))
1977         {
1978           context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
1979         }
1980 #endif /* ENABLED (JERRY_ES2015) */
1981 
1982         lexer_next_token (context_p);
1983         parser_parse_expression (context_p, PARSE_EXPR);
1984         if (context_p->token.type != LEXER_RIGHT_SQUARE)
1985         {
1986           parser_raise_error (context_p, PARSER_ERR_RIGHT_SQUARE_EXPECTED);
1987         }
1988         lexer_next_token (context_p);
1989 
1990 #if ENABLED (JERRY_ES2015)
1991         if (last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER))
1992         {
1993           parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER_PROP);
1994           continue;
1995         }
1996 #endif /* ENABLED (JERRY_ES2015) */
1997 
1998         if (PARSER_IS_MUTABLE_PUSH_LITERAL (context_p->last_cbc_opcode))
1999         {
2000           context_p->last_cbc_opcode = PARSER_PUSH_LITERAL_TO_PUSH_PROP_LITERAL (context_p->last_cbc_opcode);
2001         }
2002         else
2003         {
2004           parser_emit_cbc (context_p, CBC_PUSH_PROP);
2005         }
2006         continue;
2007       }
2008 
2009 #if ENABLED (JERRY_ES2015)
2010       case LEXER_TEMPLATE_LITERAL:
2011 #endif /* ENABLED (JERRY_ES2015) */
2012       case LEXER_LEFT_PAREN:
2013       {
2014         size_t call_arguments = 0;
2015         uint16_t opcode = CBC_CALL;
2016         bool is_eval = false;
2017 
2018         parser_push_result (context_p);
2019 
2020         if (context_p->stack_top_uint8 == LEXER_KEYW_NEW)
2021         {
2022           parser_stack_pop_uint8 (context_p);
2023           opcode = CBC_NEW;
2024         }
2025         else
2026         {
2027           if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL
2028               && context_p->last_cbc.literal_keyword_type == LEXER_KEYW_EVAL
2029               && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
2030           {
2031             is_eval = true;
2032           }
2033 
2034           if (PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode))
2035           {
2036             opcode = CBC_CALL_PROP;
2037             context_p->last_cbc_opcode = PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE (context_p->last_cbc_opcode);
2038           }
2039 #if ENABLED (JERRY_ES2015)
2040           else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR))
2041           {
2042             opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL);
2043           }
2044           else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL))
2045           {
2046             context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE);
2047             opcode = CBC_CALL_PROP;
2048           }
2049           else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
2050           {
2051             context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE);
2052             opcode = CBC_CALL_PROP;
2053           }
2054 #endif /* ENABLED (JERRY_ES2015) */
2055           else if (JERRY_UNLIKELY (context_p->status_flags & PARSER_INSIDE_WITH)
2056                    && PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode)
2057                    && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
2058           {
2059             opcode = CBC_CALL_PROP;
2060             parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE);
2061             parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_BASE);
2062           }
2063         }
2064 
2065 #if ENABLED (JERRY_ES2015)
2066         bool has_spread_element = false;
2067 
2068         if (context_p->token.type == LEXER_TEMPLATE_LITERAL)
2069         {
2070           call_arguments = parser_parse_tagged_template_literal (context_p);
2071         }
2072         else
2073         {
2074           lexer_next_token (context_p);
2075 
2076           while (context_p->token.type != LEXER_RIGHT_PAREN)
2077           {
2078             if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE)
2079             {
2080               parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
2081             }
2082 
2083             if (context_p->token.type == LEXER_THREE_DOTS)
2084             {
2085               has_spread_element = true;
2086               call_arguments++;
2087               parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SPREAD_ELEMENT);
2088               lexer_next_token (context_p);
2089             }
2090 
2091             parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
2092 
2093             if (context_p->token.type == LEXER_COMMA)
2094             {
2095               lexer_next_token (context_p);
2096               continue;
2097             }
2098 
2099             if (context_p->token.type != LEXER_RIGHT_PAREN)
2100             {
2101               parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED);
2102             }
2103 
2104             break;
2105           }
2106         }
2107 #else /* !ENABLED (JERRY_ES2015) */
2108         lexer_next_token (context_p);
2109 
2110         if (context_p->token.type != LEXER_RIGHT_PAREN)
2111         {
2112           while (true)
2113           {
2114             if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE)
2115             {
2116               parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
2117             }
2118 
2119             parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
2120 
2121             if (context_p->token.type != LEXER_COMMA)
2122             {
2123               break;
2124             }
2125             lexer_next_token (context_p);
2126           }
2127 
2128           if (context_p->token.type != LEXER_RIGHT_PAREN)
2129           {
2130             parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED);
2131           }
2132         }
2133 #endif /* ENABLED (JERRY_ES2015) */
2134 
2135         lexer_next_token (context_p);
2136 
2137         if (is_eval)
2138         {
2139           context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
2140 
2141 #if ENABLED (JERRY_ES2015)
2142           uint16_t eval_flags = PARSER_SAVE_STATUS_FLAGS (context_p->status_flags);
2143           const uint32_t required_flags = PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED;
2144 
2145           if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)
2146           {
2147             context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED;
2148           }
2149           else if (((context_p->status_flags & (required_flags | PARSER_IS_STRICT)) == required_flags)
2150                    || ((context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2151                        && !(context_p->status_flags & PARSER_IS_FUNCTION)))
2152           {
2153             eval_flags |= PARSER_GET_EVAL_FLAG (ECMA_PARSE_FUNCTION_CONTEXT);
2154           }
2155 
2156           if (eval_flags != 0)
2157           {
2158             parser_emit_cbc_ext_call (context_p, CBC_EXT_LOCAL_EVAL, eval_flags);
2159           }
2160           else
2161           {
2162 #endif /* ENABLED (JERRY_ES2015) */
2163             parser_emit_cbc (context_p, CBC_EVAL);
2164 #if ENABLED (JERRY_ES2015)
2165           }
2166 #endif /* ENABLED (JERRY_ES2015) */
2167         }
2168 
2169 #if ENABLED (JERRY_ES2015)
2170         if (has_spread_element)
2171         {
2172           uint16_t spread_opcode;
2173 
2174           if (opcode == CBC_CALL)
2175           {
2176             spread_opcode = CBC_EXT_SPREAD_CALL;
2177           }
2178           else if (opcode == CBC_CALL_PROP)
2179           {
2180             spread_opcode = CBC_EXT_SPREAD_CALL_PROP;
2181           }
2182           else if (opcode == CBC_NEW)
2183           {
2184             spread_opcode = CBC_EXT_SPREAD_NEW;
2185           }
2186           else
2187           {
2188             /* opcode is unchanged */
2189             JERRY_ASSERT (opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL));
2190             spread_opcode = CBC_EXT_SPREAD_SUPER_CALL;
2191           }
2192 
2193           parser_emit_cbc_ext_call (context_p, spread_opcode, call_arguments);
2194           continue;
2195         }
2196 #endif /* ENABLED (JERRY_ES2015) */
2197 
2198         if (call_arguments <= 1)
2199         {
2200           if (opcode == CBC_CALL)
2201           {
2202             parser_emit_cbc (context_p, (uint16_t) (CBC_CALL0 + (call_arguments * 6)));
2203             continue;
2204           }
2205           if (opcode == CBC_CALL_PROP)
2206           {
2207             parser_emit_cbc (context_p, (uint16_t) (CBC_CALL0_PROP + (call_arguments * 6)));
2208             continue;
2209           }
2210           if (opcode == CBC_NEW)
2211           {
2212             parser_emit_cbc (context_p, (uint16_t) (CBC_NEW0 + call_arguments));
2213             continue;
2214           }
2215         }
2216 
2217         if (call_arguments == 2)
2218         {
2219           if (opcode == CBC_CALL)
2220           {
2221             parser_emit_cbc (context_p, CBC_CALL2);
2222             continue;
2223           }
2224           if (opcode == CBC_CALL_PROP)
2225           {
2226             parser_flush_cbc (context_p);
2227             /* Manually adjusting stack usage. */
2228             JERRY_ASSERT (context_p->stack_depth > 0);
2229             context_p->stack_depth--;
2230             parser_emit_cbc (context_p, CBC_CALL2_PROP);
2231             continue;
2232           }
2233         }
2234 
2235         parser_emit_cbc_call (context_p, opcode, call_arguments);
2236         continue;
2237       }
2238 
2239       default:
2240       {
2241         if (context_p->stack_top_uint8 == LEXER_KEYW_NEW)
2242         {
2243           parser_push_result (context_p);
2244           parser_emit_cbc (context_p, CBC_NEW0);
2245           parser_stack_pop_uint8 (context_p);
2246           continue;
2247         }
2248 
2249         if (!(context_p->token.flags & LEXER_WAS_NEWLINE)
2250             && (context_p->token.type == LEXER_INCREASE || context_p->token.type == LEXER_DECREASE)
2251             && grouping_level != PARSE_EXPR_LEFT_HAND_SIDE)
2252         {
2253           cbc_opcode_t opcode = (context_p->token.type == LEXER_INCREASE) ? CBC_POST_INCR : CBC_POST_DECR;
2254           parser_push_result (context_p);
2255           parser_emit_unary_lvalue_opcode (context_p, opcode);
2256           lexer_next_token (context_p);
2257         }
2258         break;
2259       }
2260     }
2261     break;
2262   }
2263 
2264 #if ENABLED (JERRY_ES2015)
2265   uint8_t last_unary_token = LEXER_INCREASE;
2266 #endif /* ENABLED (JERRY_ES2015) */
2267 
2268   /* Generate byte code for the unary operators. */
2269   while (true)
2270   {
2271     uint8_t token = context_p->stack_top_uint8;
2272     if (!LEXER_IS_UNARY_OP_TOKEN (token))
2273     {
2274 #if ENABLED (JERRY_ES2015)
2275       if (context_p->token.type == LEXER_EXPONENTIATION
2276           && last_unary_token != LEXER_INCREASE
2277           && last_unary_token != LEXER_DECREASE)
2278       {
2279         parser_raise_error (context_p, PARSER_ERR_INVALID_EXPONENTIATION);
2280       }
2281 #endif /* ENABLED (JERRY_ES2015) */
2282       break;
2283     }
2284 
2285 #if ENABLED (JERRY_ES2015)
2286     last_unary_token = token;
2287 #endif /* ENABLED (JERRY_ES2015) */
2288 
2289     parser_push_result (context_p);
2290     parser_stack_pop_uint8 (context_p);
2291 
2292     if (LEXER_IS_UNARY_LVALUE_OP_TOKEN (token))
2293     {
2294       if (token == LEXER_KEYW_DELETE)
2295       {
2296         token = CBC_DELETE_PUSH_RESULT;
2297       }
2298       else
2299       {
2300         token = (uint8_t) (LEXER_UNARY_LVALUE_OP_TOKEN_TO_OPCODE (token));
2301       }
2302       parser_emit_unary_lvalue_opcode (context_p, (cbc_opcode_t) token);
2303     }
2304 #if ENABLED (JERRY_ES2015)
2305     else if (JERRY_UNLIKELY (token == LEXER_KEYW_AWAIT))
2306     {
2307       parser_emit_cbc_ext (context_p, CBC_EXT_AWAIT);
2308     }
2309 #endif /* ENABLED (JERRY_ES2015) */
2310     else
2311     {
2312       token = (uint8_t) (LEXER_UNARY_OP_TOKEN_TO_OPCODE (token));
2313 
2314       if (token == CBC_TYPEOF)
2315       {
2316         if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode)
2317             && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
2318         {
2319           parser_emit_ident_reference (context_p, CBC_TYPEOF_IDENT);
2320         }
2321         else
2322         {
2323           parser_emit_cbc (context_p, token);
2324         }
2325       }
2326       else
2327       {
2328         if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
2329         {
2330           /* It is not worth to combine with push multiple literals
2331            * since the byte code size will not decrease. */
2332           JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, token + 1));
2333           context_p->last_cbc_opcode = (uint16_t) (token + 1);
2334         }
2335         else
2336         {
2337           parser_emit_cbc (context_p, token);
2338         }
2339       }
2340     }
2341   }
2342 } /* parser_process_unary_expression */
2343 
2344 /**
2345  * Append a binary '=' token.
2346  *
2347  * @return - pushed assignment opcode onto the parser stack
2348  */
2349 static uint8_t
parser_append_binary_single_assignment_token(parser_context_t * context_p,uint32_t pattern_flags)2350 parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */
2351                                               uint32_t pattern_flags) /**< pattern flags */
2352 {
2353   JERRY_UNUSED (pattern_flags);
2354 
2355   /* Unlike other tokens, the whole byte code is saved for binary
2356    * assignment, since it has multiple forms depending on the
2357    * previous instruction. */
2358 
2359   uint8_t assign_opcode = CBC_ASSIGN;
2360 
2361   if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode)
2362       && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
2363   {
2364     parser_check_invalid_assign (context_p);
2365 
2366     uint16_t literal_index;
2367 
2368     switch (context_p->last_cbc_opcode)
2369     {
2370       case CBC_PUSH_LITERAL:
2371       {
2372         literal_index = context_p->last_cbc.literal_index;
2373         context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2374         break;
2375       }
2376       case CBC_PUSH_TWO_LITERALS:
2377       {
2378         literal_index = context_p->last_cbc.value;
2379         context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
2380         break;
2381       }
2382       case CBC_PUSH_THIS_LITERAL:
2383       {
2384         literal_index = context_p->last_cbc.literal_index;
2385         context_p->last_cbc_opcode = CBC_PUSH_THIS;
2386         parser_flush_cbc (context_p);
2387         break;
2388       }
2389       default:
2390       {
2391         JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS);
2392         literal_index = context_p->last_cbc.third_literal_index;
2393         context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
2394         break;
2395       }
2396     }
2397 
2398     assign_opcode = CBC_ASSIGN_SET_IDENT;
2399 
2400 #if ENABLED (JERRY_ES2015)
2401     if (!(pattern_flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST | PARSER_PATTERN_LOCAL)))
2402     {
2403       if (scanner_literal_is_const_reg (context_p, literal_index))
2404       {
2405         parser_stack_push_uint8 (context_p, LEXER_ASSIGN_CONST);
2406       }
2407     }
2408     else if (literal_index < PARSER_REGISTER_START)
2409     {
2410       assign_opcode = CBC_INIT_LET;
2411 
2412       if (scanner_literal_is_created (context_p, literal_index))
2413       {
2414         assign_opcode = CBC_ASSIGN_LET_CONST;
2415       }
2416       else if (pattern_flags & PARSER_PATTERN_CONST)
2417       {
2418         assign_opcode = CBC_INIT_CONST;
2419       }
2420       else if (pattern_flags & PARSER_PATTERN_LOCAL)
2421       {
2422         assign_opcode = CBC_INIT_ARG_OR_CATCH;
2423       }
2424     }
2425 #endif /* ENABLED (JERRY_ES2015) */
2426 
2427     parser_stack_push_uint16 (context_p, literal_index);
2428     JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, assign_opcode));
2429   }
2430   else if (context_p->last_cbc_opcode == CBC_PUSH_PROP)
2431   {
2432     JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, CBC_ASSIGN));
2433     context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2434   }
2435   else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL)
2436   {
2437     if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
2438     {
2439       JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL, CBC_ASSIGN_PROP_LITERAL));
2440       parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index);
2441       assign_opcode = CBC_ASSIGN_PROP_LITERAL;
2442       context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2443     }
2444     else
2445     {
2446       context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
2447     }
2448   }
2449   else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL_LITERAL)
2450   {
2451     JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_PUSH_TWO_LITERALS));
2452     context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
2453   }
2454   else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL)
2455   {
2456     if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
2457     {
2458       JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_THIS_LITERAL, CBC_ASSIGN_PROP_THIS_LITERAL));
2459       parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index);
2460       assign_opcode = CBC_ASSIGN_PROP_THIS_LITERAL;
2461       context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2462     }
2463     else
2464     {
2465       context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL;
2466     }
2467   }
2468 #if ENABLED (JERRY_ES2015)
2469   else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL))
2470   {
2471     context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE);
2472     assign_opcode = CBC_ASSIGN_SUPER;
2473   }
2474   else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
2475   {
2476     context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE);
2477     assign_opcode = CBC_ASSIGN_SUPER;
2478   }
2479 #endif /* ENABLED (JERRY_ES2015) */
2480   else
2481   {
2482     /* Invalid LeftHandSide expression. */
2483 #if ENABLED (JERRY_ES2015)
2484     parser_check_invalid_new_target (context_p, CBC_ASSIGN);
2485 #endif /* ENABLED (JERRY_ES2015) */
2486 
2487     parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
2488   }
2489 
2490   parser_stack_push_uint8 (context_p, assign_opcode);
2491   parser_stack_push_uint8 (context_p, LEXER_ASSIGN);
2492 
2493   return assign_opcode;
2494 } /* parser_append_binary_single_assignment_token */
2495 
2496 /**
2497  * Append a binary token.
2498  */
2499 static void
parser_append_binary_token(parser_context_t * context_p)2500 parser_append_binary_token (parser_context_t *context_p) /**< context */
2501 {
2502   JERRY_ASSERT (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type));
2503 
2504   parser_push_result (context_p);
2505 
2506   if (context_p->token.type == LEXER_ASSIGN)
2507   {
2508     parser_append_binary_single_assignment_token (context_p, 0);
2509     return;
2510   }
2511 
2512   if (LEXER_IS_BINARY_LVALUE_TOKEN (context_p->token.type))
2513   {
2514     if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode)
2515         && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
2516     {
2517       parser_check_invalid_assign (context_p);
2518 
2519       parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE);
2520 
2521 #if ENABLED (JERRY_ES2015)
2522       if (scanner_literal_is_const_reg (context_p, context_p->last_cbc.literal_index))
2523       {
2524         parser_stack_push_uint8 (context_p, LEXER_ASSIGN_CONST);
2525       }
2526 #endif /* ENABLED (JERRY_ES2015) */
2527     }
2528     else if (PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode))
2529     {
2530       context_p->last_cbc_opcode = PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE (context_p->last_cbc_opcode);
2531     }
2532     else
2533     {
2534       /* Invalid LeftHandSide expression. */
2535 #if ENABLED (JERRY_ES2015)
2536       parser_check_invalid_new_target (context_p, CBC_ASSIGN);
2537 #endif /* ENABLED (JERRY_ES2015) */
2538 
2539       parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
2540       parser_emit_cbc (context_p, CBC_PUSH_PROP_REFERENCE);
2541     }
2542   }
2543   else if (context_p->token.type == LEXER_LOGICAL_OR
2544            || context_p->token.type == LEXER_LOGICAL_AND)
2545   {
2546     parser_branch_t branch;
2547     uint16_t opcode = CBC_BRANCH_IF_LOGICAL_TRUE;
2548 
2549     if (context_p->token.type == LEXER_LOGICAL_AND)
2550     {
2551       opcode = CBC_BRANCH_IF_LOGICAL_FALSE;
2552     }
2553 
2554     parser_emit_cbc_forward_branch (context_p, opcode, &branch);
2555     parser_stack_push (context_p, &branch, sizeof (parser_branch_t));
2556   }
2557 
2558   parser_stack_push_uint8 (context_p, context_p->token.type);
2559 } /* parser_append_binary_token */
2560 
2561 /**
2562  * Emit opcode for binary computations.
2563  */
2564 static void
parser_process_binary_opcodes(parser_context_t * context_p,uint8_t min_prec_treshold)2565 parser_process_binary_opcodes (parser_context_t *context_p, /**< context */
2566                                uint8_t min_prec_treshold) /**< minimal precedence of tokens */
2567 {
2568   while (true)
2569   {
2570     uint8_t token = context_p->stack_top_uint8;
2571     cbc_opcode_t opcode;
2572 
2573     /* For left-to-right operators (all binary operators except assignment
2574      * and logical operators), the byte code is flushed if the precedence
2575      * of the next operator is less or equal than the current operator. For
2576      * assignment and logical operators, we add 1 to the min precendence to
2577      * force right-to-left evaluation order. */
2578 
2579     if (!LEXER_IS_BINARY_OP_TOKEN (token)
2580         || parser_binary_precedence_table[token - LEXER_FIRST_BINARY_OP] < min_prec_treshold)
2581     {
2582       return;
2583     }
2584 
2585     parser_push_result (context_p);
2586     parser_stack_pop_uint8 (context_p);
2587 
2588     if (token == LEXER_ASSIGN)
2589     {
2590       opcode = (cbc_opcode_t) context_p->stack_top_uint8;
2591       parser_stack_pop_uint8 (context_p);
2592 
2593       int32_t index = -1;
2594       if (cbc_flags[opcode] & CBC_HAS_LITERAL_ARG)
2595       {
2596         JERRY_ASSERT (opcode == CBC_ASSIGN_SET_IDENT
2597                       || opcode == CBC_ASSIGN_PROP_LITERAL
2598                       || opcode == CBC_ASSIGN_PROP_THIS_LITERAL
2599                       || opcode == CBC_ASSIGN_LET_CONST
2600                       || opcode == CBC_INIT_ARG_OR_CATCH
2601                       || opcode == CBC_INIT_LET
2602                       || opcode == CBC_INIT_CONST);
2603 
2604         index = parser_stack_pop_uint16 (context_p);
2605       }
2606 
2607 #if ENABLED (JERRY_ES2015)
2608       if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_CONST))
2609       {
2610         parser_stack_pop_uint8 (context_p);
2611         parser_emit_cbc_ext (context_p, CBC_EXT_THROW_ASSIGN_CONST_ERROR);
2612       }
2613 #endif /* ENABLED (JERRY_ES2015) */
2614 
2615       if (index >= 0)
2616       {
2617         if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL
2618             && opcode == CBC_ASSIGN_SET_IDENT)
2619         {
2620           JERRY_ASSERT (CBC_ARGS_EQ (CBC_ASSIGN_LITERAL_SET_IDENT,
2621                                      CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2));
2622 
2623           context_p->last_cbc.value = (uint16_t) index;
2624           context_p->last_cbc_opcode = CBC_ASSIGN_LITERAL_SET_IDENT;
2625           continue;
2626         }
2627 
2628         parser_emit_cbc_literal (context_p, (uint16_t) opcode, (uint16_t) index);
2629 
2630         if (opcode == CBC_ASSIGN_PROP_THIS_LITERAL
2631             && (context_p->stack_depth >= context_p->stack_limit))
2632         {
2633           /* Stack limit is increased for VM_OC_ASSIGN_PROP_THIS. Needed by vm.c. */
2634           JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit);
2635 
2636           context_p->stack_limit++;
2637 
2638           if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT)
2639           {
2640             parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
2641           }
2642         }
2643         continue;
2644       }
2645     }
2646     else if (LEXER_IS_BINARY_LVALUE_TOKEN (token))
2647     {
2648       parser_stack_push_uint8 (context_p, CBC_ASSIGN);
2649       parser_stack_push_uint8 (context_p, LEXER_ASSIGN);
2650       parser_stack_push_uint8 (context_p, lexer_convert_binary_lvalue_token_to_binary (token));
2651       continue;
2652     }
2653     else if (token == LEXER_LOGICAL_OR || token == LEXER_LOGICAL_AND)
2654     {
2655       parser_branch_t branch;
2656       parser_stack_pop (context_p, &branch, sizeof (parser_branch_t));
2657       parser_set_branch_to_current_position (context_p, &branch);
2658       continue;
2659     }
2660     else
2661     {
2662       opcode = LEXER_BINARY_OP_TOKEN_TO_OPCODE (token);
2663 
2664       if (PARSER_IS_PUSH_NUMBER (context_p->last_cbc_opcode))
2665       {
2666         lexer_convert_push_number_to_push_literal (context_p);
2667       }
2668 
2669       if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
2670       {
2671         JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, opcode + CBC_BINARY_WITH_LITERAL));
2672         context_p->last_cbc_opcode = (uint16_t) (opcode + CBC_BINARY_WITH_LITERAL);
2673         continue;
2674       }
2675       else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
2676       {
2677         JERRY_ASSERT (CBC_ARGS_EQ (opcode + CBC_BINARY_WITH_TWO_LITERALS,
2678                                    CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2));
2679         context_p->last_cbc_opcode = (uint16_t) (opcode + CBC_BINARY_WITH_TWO_LITERALS);
2680         continue;
2681       }
2682     }
2683     parser_emit_cbc (context_p, (uint16_t) opcode);
2684   }
2685 } /* parser_process_binary_opcodes */
2686 
2687 #if ENABLED (JERRY_ES2015)
2688 /**
2689  * End position marker of a pattern.
2690  */
2691 typedef struct
2692 {
2693   scanner_location_t location; /**< end position of the pattern */
2694   lexer_token_t token; /**< token at the end position */
2695 } parser_pattern_end_marker_t;
2696 
2697 /**
2698  * Literal index should not be emitted while processing rhs target value
2699  */
2700 #define PARSER_PATTERN_RHS_NO_LIT UINT16_MAX
2701 
2702 /**
2703  * Process the target of an initializer pattern.
2704  */
2705 static parser_pattern_end_marker_t
parser_pattern_get_target(parser_context_t * context_p,parser_pattern_flags_t flags)2706 parser_pattern_get_target (parser_context_t *context_p, /**< context */
2707                            parser_pattern_flags_t flags) /**< flags */
2708 {
2709   parser_pattern_end_marker_t end_marker;
2710   end_marker.token.type = LEXER_INVALID_PATTERN;
2711   parser_branch_t skip_init;
2712 
2713   if (flags & PARSER_PATTERN_TARGET_DEFAULT)
2714   {
2715     JERRY_ASSERT (flags & PARSER_PATTERN_TARGET_ON_STACK);
2716 
2717     parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
2718   }
2719 
2720   if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK)
2721   {
2722     scanner_location_t start_location;
2723 
2724     if (context_p->next_scanner_info_p->source_p != context_p->source_p
2725         || context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
2726         || (flags & PARSER_PATTERN_REST_ELEMENT))
2727     {
2728       /* Found invalid pattern, push null value to fake the rhs target. */
2729       parser_emit_cbc (context_p, CBC_PUSH_NULL);
2730     }
2731     else
2732     {
2733       JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
2734       scanner_get_location (&start_location, context_p);
2735 
2736       scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location);
2737       scanner_release_next (context_p, sizeof (scanner_location_info_t));
2738       scanner_seek (context_p);
2739       lexer_next_token (context_p);
2740 
2741       parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
2742       scanner_get_location (&(end_marker.location), context_p);
2743       end_marker.token = context_p->token;
2744 
2745       scanner_set_location (context_p, &start_location);
2746       scanner_seek (context_p);
2747       parser_flush_cbc (context_p);
2748     }
2749   }
2750 
2751   if (flags & PARSER_PATTERN_TARGET_DEFAULT)
2752   {
2753     parser_set_branch_to_current_position (context_p, &skip_init);
2754   }
2755 
2756   return end_marker;
2757 } /* parser_pattern_get_target */
2758 
2759 /**
2760  * Finalize an assignment/binding pattern.
2761  */
2762 static void
parser_pattern_finalize(parser_context_t * context_p,parser_pattern_flags_t flags,parser_pattern_end_marker_t * end_marker_p)2763 parser_pattern_finalize (parser_context_t *context_p, /**< context */
2764                          parser_pattern_flags_t flags, /**< flags */
2765                          parser_pattern_end_marker_t *end_marker_p) /**< pattern end position  */
2766 {
2767   if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK)
2768   {
2769     if (end_marker_p->token.type == LEXER_INVALID_PATTERN)
2770     {
2771       parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
2772     }
2773 
2774     scanner_set_location (context_p, &(end_marker_p->location));
2775     context_p->token = end_marker_p->token;
2776   }
2777   else
2778   {
2779     JERRY_ASSERT (!(flags & PARSER_PATTERN_TARGET_DEFAULT));
2780     lexer_next_token (context_p);
2781   }
2782 
2783   if ((flags & (PARSER_PATTERN_BINDING | PARSER_PATTERN_NESTED_PATTERN)) == PARSER_PATTERN_BINDING)
2784   {
2785     /* Pop the result of the expression. */
2786     parser_emit_cbc (context_p, CBC_POP);
2787   }
2788 
2789   parser_flush_cbc (context_p);
2790 } /* parser_pattern_finalize */
2791 
2792 /**
2793  * Emit right-hand-side target value.
2794  */
2795 static void
parser_pattern_emit_rhs(parser_context_t * context_p,uint16_t rhs_opcode,uint16_t literal_index)2796 parser_pattern_emit_rhs (parser_context_t *context_p, /**< context */
2797                          uint16_t rhs_opcode, /**< opcode to process the rhs value */
2798                          uint16_t literal_index) /**< literal index for object pattern */
2799 {
2800   if (literal_index != PARSER_PATTERN_RHS_NO_LIT)
2801   {
2802     parser_emit_cbc_ext_literal (context_p, rhs_opcode, literal_index);
2803   }
2804   else
2805   {
2806     parser_emit_cbc_ext (context_p, rhs_opcode);
2807   }
2808 } /* parser_pattern_emit_rhs */
2809 
2810 /**
2811  * Form an assignment from a pattern.
2812  */
2813 static void
parser_pattern_form_assignment(parser_context_t * context_p,parser_pattern_flags_t flags,uint16_t rhs_opcode,uint16_t literal_index,parser_line_counter_t ident_line_counter)2814 parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
2815                                 parser_pattern_flags_t flags, /**< flags */
2816                                 uint16_t rhs_opcode, /**< opcode to process the rhs value */
2817                                 uint16_t literal_index, /**< literal index for object pattern */
2818                                 parser_line_counter_t ident_line_counter) /**< identifier line counter */
2819 {
2820   JERRY_UNUSED (ident_line_counter);
2821 
2822   parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
2823   uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, flags);
2824 
2825   if (flags & PARSER_PATTERN_ARRAY)
2826   {
2827     int32_t stack_adjustment = (CBC_STACK_ADJUST_BASE - (cbc_flags[assign_opcode] >> CBC_STACK_ADJUST_SHIFT));
2828     JERRY_ASSERT (stack_adjustment >= 1 && stack_adjustment <= 3);
2829 
2830     rhs_opcode = (uint16_t) (rhs_opcode + stack_adjustment - 1);
2831   }
2832 
2833   parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
2834 
2835   if (context_p->token.type == LEXER_ASSIGN)
2836   {
2837     parser_branch_t skip_init;
2838     lexer_next_token (context_p);
2839     parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
2840 
2841     parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
2842     parser_set_branch_to_current_position (context_p, &skip_init);
2843   }
2844 
2845   parser_process_binary_opcodes (context_p, 0);
2846 
2847   JERRY_ASSERT (context_p->stack_top_uint8 == LEXER_EXPRESSION_START);
2848   parser_stack_pop_uint8 (context_p);
2849 
2850 #if ENABLED (JERRY_DEBUGGER)
2851   if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2852       && ident_line_counter != context_p->last_breakpoint_line)
2853   {
2854     parser_emit_cbc (context_p, CBC_BREAKPOINT_DISABLED);
2855     parser_flush_cbc (context_p);
2856 
2857     parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST, ident_line_counter);
2858 
2859     context_p->last_breakpoint_line = ident_line_counter;
2860   }
2861 #endif /* ENABLED (JERRY_DEBUGGER) */
2862 
2863 #if ENABLED (JERRY_LINE_INFO)
2864   if (ident_line_counter != context_p->last_line_info_line)
2865   {
2866     parser_emit_line_info (context_p, ident_line_counter, false);
2867   }
2868 #endif /* ENABLED (JERRY_LINE_INFO) */
2869 } /* parser_pattern_form_assignment */
2870 
2871 /**
2872  * Parse pattern inside a pattern.
2873  */
2874 static void
parser_pattern_process_nested_pattern(parser_context_t * context_p,parser_pattern_flags_t flags,uint16_t rhs_opcode,uint16_t literal_index)2875 parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context */
2876                                        parser_pattern_flags_t flags, /**< flags */
2877                                        uint16_t rhs_opcode, /**< opcode to process the rhs value */
2878                                        uint16_t literal_index) /**< literal index for object pattern */
2879 {
2880   JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE);
2881 
2882   parser_pattern_flags_t options = (PARSER_PATTERN_NESTED_PATTERN
2883                                     | PARSER_PATTERN_TARGET_ON_STACK
2884                                     | (flags & (PARSER_PATTERN_BINDING
2885                                                 | PARSER_PATTERN_LET
2886                                                 | PARSER_PATTERN_CONST
2887                                                 | PARSER_PATTERN_LOCAL
2888                                                 | PARSER_PATTERN_REST_ELEMENT
2889                                                 | PARSER_PATTERN_ARGUMENTS)));
2890 
2891   if (context_p->next_scanner_info_p->source_p == context_p->source_p)
2892   {
2893     options |= PARSER_PATTERN_TARGET_DEFAULT;
2894   }
2895 
2896   parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
2897 
2898   if (context_p->token.type == LEXER_LEFT_BRACE)
2899   {
2900     parser_parse_object_initializer (context_p, options);
2901   }
2902   else
2903   {
2904     parser_parse_array_initializer (context_p, options);
2905   }
2906 
2907   parser_emit_cbc (context_p, CBC_POP);
2908 } /* parser_pattern_process_nested_pattern */
2909 
2910 /**
2911  * Process the current {Binding, Assignment}Property
2912  */
2913 static void
parser_pattern_process_assignment(parser_context_t * context_p,parser_pattern_flags_t flags,uint16_t rhs_opcode,uint16_t literal_index,lexer_token_type_t end_type)2914 parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
2915                                    parser_pattern_flags_t flags, /**< flags */
2916                                    uint16_t rhs_opcode, /**< opcode to process the rhs value */
2917                                    uint16_t literal_index, /**< literal index for object pattern */
2918                                    lexer_token_type_t end_type) /**< end type token */
2919 {
2920   if (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE)
2921   {
2922     parser_pattern_process_nested_pattern (context_p, flags, rhs_opcode, literal_index);
2923     return;
2924   }
2925 
2926   parser_line_counter_t ident_line_counter = context_p->token.line;
2927 
2928   if (flags & PARSER_PATTERN_BINDING)
2929   {
2930     if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
2931     {
2932       parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
2933     }
2934 
2935     lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
2936 
2937     if (flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST)
2938         && context_p->token.keyword_type == LEXER_KEYW_LET)
2939     {
2940       parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING);
2941     }
2942 
2943     if (context_p->next_scanner_info_p->source_p == context_p->source_p)
2944     {
2945       JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
2946       parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
2947     }
2948 
2949     if (flags & PARSER_PATTERN_ARGUMENTS)
2950     {
2951       if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)
2952       {
2953         parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
2954       }
2955       context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
2956     }
2957 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2958     parser_module_append_export_name (context_p);
2959 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2960 
2961     parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
2962     lexer_next_token (context_p);
2963 
2964     if (context_p->token.type != end_type
2965         && context_p->token.type != LEXER_ASSIGN
2966         && context_p->token.type != LEXER_COMMA)
2967     {
2968       parser_raise_error (context_p, PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION);
2969     }
2970   }
2971   else
2972   {
2973     parser_flush_cbc (context_p);
2974     parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
2975 
2976     if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) && !PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode))
2977     {
2978       parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
2979     }
2980   }
2981 
2982   parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter);
2983 } /* parser_pattern_process_assignment */
2984 
2985 /**
2986  * Parse array initializer.
2987  */
2988 static void
parser_parse_array_initializer(parser_context_t * context_p,parser_pattern_flags_t flags)2989 parser_parse_array_initializer (parser_context_t *context_p, /**< context */
2990                                 parser_pattern_flags_t flags) /**< flags */
2991 {
2992   parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags);
2993   flags |= PARSER_PATTERN_ARRAY;
2994 
2995   lexer_next_token (context_p);
2996   parser_emit_cbc_ext (context_p, CBC_EXT_GET_ITERATOR);
2997 
2998   while (context_p->token.type != LEXER_RIGHT_SQUARE)
2999   {
3000     uint16_t rhs_opcode = CBC_EXT_ITERATOR_STEP;
3001 
3002     if (context_p->token.type == LEXER_COMMA)
3003     {
3004       parser_emit_cbc_ext (context_p, rhs_opcode);
3005       parser_emit_cbc (context_p, CBC_POP);
3006       lexer_next_token (context_p);
3007       continue;
3008     }
3009 
3010     parser_pattern_flags_t options = flags;
3011 
3012     if (context_p->token.type == LEXER_THREE_DOTS)
3013     {
3014       lexer_next_token (context_p);
3015       rhs_opcode = CBC_EXT_REST_INITIALIZER;
3016       options |= PARSER_PATTERN_REST_ELEMENT;
3017     }
3018 
3019     parser_pattern_process_assignment (context_p, options, rhs_opcode, PARSER_PATTERN_RHS_NO_LIT, LEXER_RIGHT_SQUARE);
3020 
3021     if (context_p->token.type == LEXER_COMMA && rhs_opcode != CBC_EXT_REST_INITIALIZER)
3022     {
3023       lexer_next_token (context_p);
3024     }
3025     else if (context_p->token.type != LEXER_RIGHT_SQUARE)
3026     {
3027       parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
3028     }
3029   }
3030 
3031   /* close the iterator */
3032   parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CLOSE);
3033 
3034   parser_pattern_finalize (context_p, flags, &end_pos);
3035 } /* parser_parse_array_initializer */
3036 
3037 /**
3038  * Parse object initializer.
3039  */
3040 static void
parser_parse_object_initializer(parser_context_t * context_p,parser_pattern_flags_t flags)3041 parser_parse_object_initializer (parser_context_t *context_p, /**< context */
3042                                  parser_pattern_flags_t flags) /**< flags */
3043 {
3044   parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags);
3045 
3046   /* 12.14.5.2:  ObjectAssignmentPattern : { } */
3047   if (lexer_check_next_character (context_p, LIT_CHAR_RIGHT_BRACE))
3048   {
3049     parser_emit_cbc_ext (context_p, CBC_EXT_REQUIRE_OBJECT_COERCIBLE);
3050     lexer_consume_next_character (context_p);
3051     parser_pattern_finalize (context_p, flags, &end_pos);
3052     return;
3053   }
3054 
3055   while (true)
3056   {
3057     lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN);
3058 
3059     uint16_t prop_index = context_p->lit_object.index;
3060     parser_line_counter_t start_line = context_p->token.line;
3061     parser_line_counter_t start_column = context_p->token.column;
3062     uint16_t push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL;
3063 
3064     if (context_p->token.type == LEXER_RIGHT_BRACE)
3065     {
3066       break;
3067     }
3068     else if (context_p->token.type == LEXER_RIGHT_SQUARE)
3069     {
3070       prop_index = PARSER_PATTERN_RHS_NO_LIT;
3071       push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP;
3072     }
3073 
3074     if (context_p->next_scanner_info_p->source_p == context_p->source_p)
3075     {
3076       JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
3077       parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
3078     }
3079 
3080     lexer_next_token (context_p);
3081 
3082     if (context_p->token.type == LEXER_COLON)
3083     {
3084       lexer_next_token (context_p);
3085       parser_pattern_process_assignment (context_p, flags, push_prop_opcode, prop_index, LEXER_RIGHT_BRACE);
3086     }
3087     else
3088     {
3089       if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
3090       {
3091         parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
3092       }
3093 
3094       if (context_p->token.type != LEXER_RIGHT_BRACE
3095           && context_p->token.type != LEXER_ASSIGN
3096           && context_p->token.type != LEXER_COMMA)
3097       {
3098         parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
3099       }
3100 
3101       parser_reparse_as_common_identifier (context_p, start_line, start_column);
3102       lexer_next_token (context_p);
3103 
3104       JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE
3105                     || context_p->token.type == LEXER_ASSIGN
3106                     || context_p->token.type == LEXER_COMMA);
3107 
3108       if (flags & PARSER_PATTERN_ARGUMENTS)
3109       {
3110         if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)
3111         {
3112           parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
3113         }
3114         context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
3115       }
3116 
3117 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
3118       parser_module_append_export_name (context_p);
3119 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
3120 
3121       parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
3122       parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line);
3123     }
3124 
3125     if (context_p->token.type == LEXER_RIGHT_BRACE)
3126     {
3127       break;
3128     }
3129     else if (context_p->token.type != LEXER_COMMA)
3130     {
3131       parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
3132     }
3133   }
3134 
3135   parser_pattern_finalize (context_p, flags, &end_pos);
3136 } /* parser_parse_object_initializer */
3137 
3138 /**
3139  * Parse an initializer.
3140  */
3141 void
parser_parse_initializer(parser_context_t * context_p,parser_pattern_flags_t flags)3142 parser_parse_initializer (parser_context_t *context_p, /**< context */
3143                           parser_pattern_flags_t flags) /**< flags */
3144 {
3145   if (context_p->token.type == LEXER_LEFT_BRACE)
3146   {
3147     parser_parse_object_initializer (context_p, flags);
3148   }
3149   else
3150   {
3151     JERRY_ASSERT (context_p->token.type == LEXER_LEFT_SQUARE);
3152     parser_parse_array_initializer (context_p, flags);
3153   }
3154 } /* parser_parse_initializer */
3155 
3156 /**
3157  * Parse an initializer using the next character.
3158  */
3159 void
parser_parse_initializer_by_next_char(parser_context_t * context_p,parser_pattern_flags_t flags)3160 parser_parse_initializer_by_next_char (parser_context_t *context_p, /**< context */
3161                                        parser_pattern_flags_t flags) /**< flags */
3162 {
3163   JERRY_ASSERT (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE));
3164 
3165   if (lexer_consume_next_character (context_p) == LIT_CHAR_LEFT_BRACE)
3166   {
3167     parser_parse_object_initializer (context_p, flags);
3168   }
3169   else
3170   {
3171     parser_parse_array_initializer (context_p, flags);
3172   }
3173 } /* parser_parse_initializer_by_next_char */
3174 
3175 #endif /* ENABLED (JERRY_ES2015) */
3176 
3177 /**
3178  * Process ternary expression.
3179  */
3180 static void
parser_process_ternary_expression(parser_context_t * context_p)3181 parser_process_ternary_expression (parser_context_t *context_p) /**< context */
3182 {
3183   JERRY_ASSERT (context_p->token.type == LEXER_QUESTION_MARK);
3184 
3185   cbc_opcode_t opcode = CBC_BRANCH_IF_FALSE_FORWARD;
3186   parser_branch_t cond_branch;
3187   parser_branch_t uncond_branch;
3188 
3189   parser_push_result (context_p);
3190 
3191   if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT)
3192   {
3193     context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
3194     opcode = CBC_BRANCH_IF_TRUE_FORWARD;
3195   }
3196 
3197   parser_emit_cbc_forward_branch (context_p, (uint16_t) opcode, &cond_branch);
3198 
3199   lexer_next_token (context_p);
3200   parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
3201   parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &uncond_branch);
3202   parser_set_branch_to_current_position (context_p, &cond_branch);
3203 
3204   /* Although byte code is constructed for two branches,
3205    * only one of them will be executed. To reflect this
3206    * the stack is manually adjusted. */
3207   JERRY_ASSERT (context_p->stack_depth > 0);
3208   context_p->stack_depth--;
3209 
3210   if (context_p->token.type != LEXER_COLON)
3211   {
3212     parser_raise_error (context_p, PARSER_ERR_COLON_FOR_CONDITIONAL_EXPECTED);
3213   }
3214 
3215   lexer_next_token (context_p);
3216 
3217   parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
3218   parser_set_branch_to_current_position (context_p, &uncond_branch);
3219 
3220   /* Last opcode rewrite is not allowed because
3221    * the result may come from the first branch. */
3222   parser_flush_cbc (context_p);
3223 
3224   parser_process_binary_opcodes (context_p, 0);
3225 } /* parser_process_ternary_expression */
3226 
3227 /**
3228  * Process expression sequence.
3229  */
3230 static void
parser_process_expression_sequence(parser_context_t * context_p)3231 parser_process_expression_sequence (parser_context_t *context_p) /**< context */
3232 {
3233   if (!CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode))
3234   {
3235     parser_emit_cbc (context_p, CBC_POP);
3236   }
3237 
3238   if (context_p->stack_top_uint8 == LEXER_LEFT_PAREN)
3239   {
3240     parser_mem_page_t *page_p = context_p->stack.first_p;
3241 
3242     JERRY_ASSERT (page_p != NULL);
3243 
3244     page_p->bytes[context_p->stack.last_position - 1] = LEXER_COMMA_SEP_LIST;
3245     context_p->stack_top_uint8 = LEXER_COMMA_SEP_LIST;
3246   }
3247 
3248   lexer_next_token (context_p);
3249 } /* parser_process_expression_sequence */
3250 
3251 /**
3252  * Process group expression.
3253  */
3254 static void
parser_process_group_expression(parser_context_t * context_p,size_t * grouping_level_p)3255 parser_process_group_expression (parser_context_t *context_p, /**< context */
3256                                  size_t *grouping_level_p) /**< grouping level */
3257 {
3258   JERRY_ASSERT (*grouping_level_p >= PARSER_GROUPING_LEVEL_INCREASE);
3259   (*grouping_level_p) -= PARSER_GROUPING_LEVEL_INCREASE;
3260 
3261   if (context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST)
3262   {
3263     parser_push_result (context_p);
3264     parser_flush_cbc (context_p);
3265   }
3266 
3267   parser_stack_pop_uint8 (context_p);
3268   lexer_next_token (context_p);
3269 
3270 #if ENABLED (JERRY_ES2015)
3271   /* Lookahead for anonymous function declaration after '=' token when the assignment base is LHS expression
3272      with a single indentifier in it. e.g.: (a) = function () {} */
3273   if (JERRY_UNLIKELY (context_p->token.type == LEXER_ASSIGN
3274                       && PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode)
3275                       && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL
3276                       && parser_is_assignment_expr (context_p)))
3277   {
3278     parser_stack_push_uint8 (context_p, LEXER_ASSIGN_GROUP_EXPR);
3279   }
3280 #endif /* ENABLED (JERRY_ES2015) */
3281 
3282 } /* parser_process_group_expression */
3283 
3284 /**
3285  * Parse block expression.
3286  */
3287 void
parser_parse_block_expression(parser_context_t * context_p,int options)3288 parser_parse_block_expression (parser_context_t *context_p, /**< context */
3289                                int options) /**< option flags */
3290 {
3291   parser_parse_expression (context_p, options | PARSE_EXPR_NO_PUSH_RESULT);
3292 
3293   if (CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode))
3294   {
3295     JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, context_p->last_cbc_opcode + 2));
3296     PARSER_PLUS_EQUAL_U16 (context_p->last_cbc_opcode, 2);
3297     parser_flush_cbc (context_p);
3298   }
3299   else
3300   {
3301     parser_emit_cbc (context_p, CBC_POP_BLOCK);
3302   }
3303 } /* parser_parse_block_expression */
3304 
3305 /**
3306  * Parse expression statement.
3307  */
3308 void
parser_parse_expression_statement(parser_context_t * context_p,int options)3309 parser_parse_expression_statement (parser_context_t *context_p, /**< context */
3310                                    int options) /**< option flags */
3311 {
3312   parser_parse_expression (context_p, options | PARSE_EXPR_NO_PUSH_RESULT);
3313 
3314   if (!CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode))
3315   {
3316     parser_emit_cbc (context_p, CBC_POP);
3317   }
3318 } /* parser_parse_expression_statement */
3319 
3320 JERRY_STATIC_ASSERT (PARSE_EXPR_LEFT_HAND_SIDE == 0x1,
3321                      value_of_parse_expr_left_hand_side_must_be_1);
3322 
3323 /**
3324  * Parse expression.
3325  */
3326 void
parser_parse_expression(parser_context_t * context_p,int options)3327 parser_parse_expression (parser_context_t *context_p, /**< context */
3328                          int options) /**< option flags */
3329 {
3330   size_t grouping_level = (options & PARSE_EXPR_LEFT_HAND_SIDE);
3331 
3332   parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
3333 
3334   if (options & PARSE_EXPR_HAS_LITERAL)
3335   {
3336     JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
3337     goto process_unary_expression;
3338   }
3339 
3340   while (true)
3341   {
3342     if (parser_parse_unary_expression (context_p, &grouping_level))
3343     {
3344       parser_process_binary_opcodes (context_p, 0);
3345       break;
3346     }
3347 
3348     while (true)
3349     {
3350 process_unary_expression:
3351       parser_process_unary_expression (context_p, grouping_level);
3352 
3353       if (JERRY_LIKELY (grouping_level != PARSE_EXPR_LEFT_HAND_SIDE))
3354       {
3355         uint8_t min_prec_treshold = 0;
3356 
3357         if (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type))
3358         {
3359           min_prec_treshold = parser_binary_precedence_table[context_p->token.type - LEXER_FIRST_BINARY_OP];
3360 
3361 #if ENABLED (JERRY_ES2015)
3362           /* Check for BINARY_LVALUE tokens + LEXER_LOGICAL_OR + LEXER_LOGICAL_AND + LEXER_EXPONENTIATION */
3363           if ((min_prec_treshold == PARSER_RIGHT_TO_LEFT_ORDER_EXPONENTIATION)
3364               || (min_prec_treshold <= PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE
3365                   && min_prec_treshold != PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE))
3366           {
3367             /* Right-to-left evaluation order. */
3368             min_prec_treshold++;
3369           }
3370 #else /* !ENABLED (JERRY_ES2015) */
3371           /* Check for BINARY_LVALUE tokens + LEXER_LOGICAL_OR + LEXER_LOGICAL_AND */
3372           if (min_prec_treshold <= PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE
3373               && min_prec_treshold != PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE)
3374           {
3375             /* Right-to-left evaluation order. */
3376             min_prec_treshold++;
3377           }
3378 #endif /* ENABLED (JERRY_ES2015) */
3379         }
3380 
3381         parser_process_binary_opcodes (context_p, min_prec_treshold);
3382       }
3383 
3384       if (context_p->token.type == LEXER_RIGHT_PAREN
3385           && (context_p->stack_top_uint8 == LEXER_LEFT_PAREN
3386               || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST))
3387       {
3388         parser_process_group_expression (context_p, &grouping_level);
3389         continue;
3390       }
3391 
3392       break;
3393     }
3394 
3395     if (grouping_level == PARSE_EXPR_LEFT_HAND_SIDE)
3396     {
3397       break;
3398     }
3399 
3400     if (JERRY_UNLIKELY (context_p->token.type == LEXER_QUESTION_MARK))
3401     {
3402       parser_process_ternary_expression (context_p);
3403 
3404       if (context_p->token.type == LEXER_RIGHT_PAREN)
3405       {
3406         goto process_unary_expression;
3407       }
3408     }
3409     else if (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type))
3410     {
3411       parser_append_binary_token (context_p);
3412       lexer_next_token (context_p);
3413       continue;
3414     }
3415 
3416     if (JERRY_UNLIKELY (context_p->token.type == LEXER_COMMA)
3417         && (!(options & PARSE_EXPR_NO_COMMA) || grouping_level >= PARSER_GROUPING_LEVEL_INCREASE))
3418     {
3419       parser_process_expression_sequence (context_p);
3420       continue;
3421     }
3422 
3423     break;
3424   }
3425 
3426   if (grouping_level >= PARSER_GROUPING_LEVEL_INCREASE)
3427   {
3428     parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED);
3429   }
3430 
3431   JERRY_ASSERT (context_p->stack_top_uint8 == LEXER_EXPRESSION_START);
3432   parser_stack_pop_uint8 (context_p);
3433 
3434   if (!(options & PARSE_EXPR_NO_PUSH_RESULT))
3435   {
3436     parser_push_result (context_p);
3437   }
3438 } /* parser_parse_expression */
3439 
3440 /**
3441  * @}
3442  * @}
3443  * @}
3444  */
3445 
3446 #endif /* ENABLED (JERRY_PARSER) */
3447