parser_parse_object_initializer (parser_context_t *context_p, /**< context */
                                 parser_pattern_flags_t flags) /**< flags */
{
  parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags);

  /* 12.14.5.2:  ObjectAssignmentPattern : { } */
  if (lexer_check_next_character (context_p, LIT_CHAR_RIGHT_BRACE))
  {
    parser_emit_cbc_ext (context_p, CBC_EXT_REQUIRE_OBJECT_COERCIBLE);
    lexer_consume_next_character (context_p);
    parser_pattern_finalize (context_p, flags, &end_pos);
    return;
  }

  cbc_ext_opcode_t context_opcode = CBC_EXT_OBJ_INIT_CONTEXT_CREATE;

  if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
  {
    context_opcode = CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE;
  }

  parser_emit_cbc_ext (context_p, context_opcode);

  while (true)
  {
    lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN);

    uint16_t prop_index = context_p->lit_object.index;
    parser_line_counter_t start_line = context_p->token.line;
    parser_line_counter_t start_column = context_p->token.column;
    uint16_t push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL;

    if (context_p->token.type == LEXER_RIGHT_BRACE)
    {
      break;
    }

    if (context_p->token.type == LEXER_THREE_DOTS)
    {
      lexer_next_token (context_p);

      flags |= PARSER_PATTERN_REST_ELEMENT;

      if (parser_pattern_process_assignment (context_p,
                                             flags,
                                             CBC_EXT_OBJ_INIT_PUSH_REST,
                                             PARSER_PATTERN_RHS_NO_LIT,
                                             LEXER_RIGHT_BRACE))
      {
        parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT);
      }

      if (context_p->token.type != LEXER_RIGHT_BRACE)
      {
        parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
      }

      /* Checked at the end because there might be syntax errors before. */
      JERRY_ASSERT (flags & PARSER_PATTERN_HAS_REST_ELEMENT);
      break;
    }

    if (context_p->token.type == LEXER_RIGHT_SQUARE)
    {
      prop_index = PARSER_PATTERN_RHS_NO_LIT;
      push_prop_opcode = ((flags & PARSER_PATTERN_HAS_REST_ELEMENT) ? CBC_EXT_INITIALIZER_PUSH_NAME
                                                                    : CBC_EXT_INITIALIZER_PUSH_PROP);
    }
    else if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
    {
      push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL;
    }

    if (context_p->next_scanner_info_p->source_p == context_p->source_p)
    {
      JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
      parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
    }

    lexer_next_token (context_p);

    if (context_p->token.type == LEXER_COLON)
    {
      lexer_next_token (context_p);
      parser_pattern_process_assignment (context_p, flags, push_prop_opcode, prop_index, LEXER_RIGHT_BRACE);
    }
    else
    {
      if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_NAME
          || push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
      {
        parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
      }

      if (context_p->token.type != LEXER_RIGHT_BRACE
          && context_p->token.type != LEXER_ASSIGN
          && context_p->token.type != LEXER_COMMA)
      {
        parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
      }

      parser_reparse_as_common_identifier (context_p, start_line, start_column);

      if (flags & PARSER_PATTERN_ARGUMENTS)
      {
        if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)
        {
          parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
        }
        context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
      }

#if JERRY_MODULE_SYSTEM
      parser_module_append_export_name (context_p);
#endif /* JERRY_MODULE_SYSTEM */

      parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);

      lexer_next_token (context_p);
      JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE
                    || context_p->token.type == LEXER_ASSIGN
                    || context_p->token.type == LEXER_COMMA);

      parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line);
#if JERRY_LINE_INFO
      parser_line_info_append (context_p, start_line, start_column);
#endif /* JERRY_LINE_INFO */
    }

    if (context_p->token.type == LEXER_RIGHT_BRACE)
    {
      break;
    }
    else if (context_p->token.type != LEXER_COMMA)
    {
      parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
    }
  }

  if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
  {
    PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, (PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION
                                                     - PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION));
  }

  parser_emit_cbc_ext (context_p, CBC_EXT_OBJ_INIT_CONTEXT_END);

  parser_pattern_finalize (context_p, flags, &end_pos);
} /* parser_parse_object_initializer */
parser_parse_object_initializer (parser_context_t *context_p,  
                                 parser_pattern_flags_t flags)  
{
  parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags);

   
  if (lexer_check_next_character (context_p, LIT_CHAR_RIGHT_BRACE))
  {
    parser_emit_cbc_ext (context_p, CBC_EXT_REQUIRE_OBJECT_COERCIBLE);
    lexer_consume_next_character (context_p);
    parser_pattern_finalize (context_p, flags, &end_pos);
    return;
  }

  cbc_ext_opcode_t context_opcode = CBC_EXT_OBJ_INIT_CONTEXT_CREATE;

  if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
  {
    context_opcode = CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE;
  }

  parser_emit_cbc_ext (context_p, context_opcode);

  while (true)
  {
    lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN);

    uint16_t prop_index = context_p->lit_object.index;
    parser_line_counter_t start_line = context_p->token.line;
    parser_line_counter_t start_column = context_p->token.column;
    uint16_t push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL;

    if (context_p->token.type == LEXER_RIGHT_BRACE)
    {
      break;
    }

    if (context_p->token.type == LEXER_THREE_DOTS)
    {
      lexer_next_token (context_p);

      flags |= PARSER_PATTERN_REST_ELEMENT;

      if (parser_pattern_process_assignment (context_p,
                                             flags,
                                             CBC_EXT_OBJ_INIT_PUSH_REST,
                                             PARSER_PATTERN_RHS_NO_LIT,
                                             LEXER_RIGHT_BRACE))
      {
        parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT);
      }

      if (context_p->token.type != LEXER_RIGHT_BRACE)
      {
        parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
      }

       
      JERRY_ASSERT (flags & PARSER_PATTERN_HAS_REST_ELEMENT);
      break;
    }

    if (context_p->token.type == LEXER_RIGHT_SQUARE)
    {
      prop_index = PARSER_PATTERN_RHS_NO_LIT;
      push_prop_opcode = ((flags & PARSER_PATTERN_HAS_REST_ELEMENT) ? CBC_EXT_INITIALIZER_PUSH_NAME
                                                                    : CBC_EXT_INITIALIZER_PUSH_PROP);
    }
    else if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
    {
      push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL;
    }

    if (context_p->next_scanner_info_p->source_p == context_p->source_p)
    {
      JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
      parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
    }

    lexer_next_token (context_p);

    if (context_p->token.type == LEXER_COLON)
    {
      lexer_next_token (context_p);
      parser_pattern_process_assignment (context_p, flags, push_prop_opcode, prop_index, LEXER_RIGHT_BRACE);
    }
    else
    {
      if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_NAME
          || push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
      {
        parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
      }

      if (context_p->token.type != LEXER_RIGHT_BRACE
          && context_p->token.type != LEXER_ASSIGN
          && context_p->token.type != LEXER_COMMA)
      {
        parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
      }

      parser_reparse_as_common_identifier (context_p, start_line, start_column);

      if (flags & PARSER_PATTERN_ARGUMENTS)
      {
        if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)
        {
          parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
        }
        context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
      }

#if JERRY_MODULE_SYSTEM
      parser_module_append_export_name (context_p);
#endif  

      parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);

      lexer_next_token (context_p);
      JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE
                    || context_p->token.type == LEXER_ASSIGN
                    || context_p->token.type == LEXER_COMMA);

      parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line);
#if JERRY_LINE_INFO
      parser_line_info_append (context_p, start_line, start_column);
#endif  
    }

    if (context_p->token.type == LEXER_RIGHT_BRACE)
    {
      break;
    }
    else if (context_p->token.type != LEXER_COMMA)
    {
      parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED);
    }
  }

  if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
  {
    PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, (PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION
                                                     - PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION));
  }

  parser_emit_cbc_ext (context_p, CBC_EXT_OBJ_INIT_CONTEXT_END);

  parser_pattern_finalize (context_p, flags, &end_pos);
}  