scanner_push_class_declaration (parser_context_t *context_p, /**< context */
                                scanner_context_t *scanner_context_p, /* scanner context */
                                uint8_t stack_mode) /**< stack mode */
{
  JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);

  const uint8_t *source_p = context_p->source_p;
  lexer_lit_location_t *literal_p = NULL;

#if JERRY_MODULE_SYSTEM
  bool is_export_default = context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT;
  JERRY_ASSERT (!is_export_default || stack_mode == SCAN_STACK_CLASS_EXPRESSION);
#endif /* JERRY_MODULE_SYSTEM */

  parser_stack_push_uint8 (context_p, stack_mode);
  lexer_next_token (context_p);

  bool class_has_name = (context_p->token.type == LEXER_LITERAL
                         && context_p->token.lit_location.type == LEXER_IDENT_LITERAL);

  if (class_has_name)
  {
    if (stack_mode == SCAN_STACK_CLASS_STATEMENT)
    {
      literal_p = scanner_add_literal (context_p, scanner_context_p);
      scanner_context_p->active_literal_pool_p->no_declarations++;
    }
#if JERRY_MODULE_SYSTEM
    else if (is_export_default)
    {
      literal_p = scanner_add_literal (context_p, scanner_context_p);
      scanner_context_p->active_literal_pool_p->no_declarations++;

      scanner_detect_invalid_let (context_p, literal_p);

      if (literal_p->type & SCANNER_LITERAL_IS_USED)
      {
        literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
      }

      literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
    }
#endif /* JERRY_MODULE_SYSTEM */
  }

  scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);

  if (class_has_name)
  {
    scanner_add_literal (context_p, scanner_context_p);
    scanner_context_p->active_literal_pool_p->no_declarations++;
  }
#if JERRY_MODULE_SYSTEM
  else if (is_export_default)
  {
    lexer_lit_location_t *name_literal_p;
    name_literal_p = scanner_add_custom_literal (context_p,
                                                 scanner_context_p->active_literal_pool_p->prev_p,
                                                 &lexer_default_literal);

    name_literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
    scanner_context_p->active_literal_pool_p->no_declarations++;
  }
#endif /* JERRY_MODULE_SYSTEM */

  literal_pool_p->source_p = source_p;
  literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CLASS_NAME;

  parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR);
  scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;

  return literal_p;
} /* scanner_push_class_declaration */
scanner_push_class_declaration (parser_context_t *context_p,  
                                scanner_context_t *scanner_context_p,  
                                uint8_t stack_mode)  
{
  JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);

  const uint8_t *source_p = context_p->source_p;
  lexer_lit_location_t *literal_p = NULL;

#if JERRY_MODULE_SYSTEM
  bool is_export_default = context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT;
  JERRY_ASSERT (!is_export_default || stack_mode == SCAN_STACK_CLASS_EXPRESSION);
#endif  

  parser_stack_push_uint8 (context_p, stack_mode);
  lexer_next_token (context_p);

  bool class_has_name = (context_p->token.type == LEXER_LITERAL
                         && context_p->token.lit_location.type == LEXER_IDENT_LITERAL);

  if (class_has_name)
  {
    if (stack_mode == SCAN_STACK_CLASS_STATEMENT)
    {
      literal_p = scanner_add_literal (context_p, scanner_context_p);
      scanner_context_p->active_literal_pool_p->no_declarations++;
    }
#if JERRY_MODULE_SYSTEM
    else if (is_export_default)
    {
      literal_p = scanner_add_literal (context_p, scanner_context_p);
      scanner_context_p->active_literal_pool_p->no_declarations++;

      scanner_detect_invalid_let (context_p, literal_p);

      if (literal_p->type & SCANNER_LITERAL_IS_USED)
      {
        literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
      }

      literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
    }
#endif  
  }

  scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);

  if (class_has_name)
  {
    scanner_add_literal (context_p, scanner_context_p);
    scanner_context_p->active_literal_pool_p->no_declarations++;
  }
#if JERRY_MODULE_SYSTEM
  else if (is_export_default)
  {
    lexer_lit_location_t *name_literal_p;
    name_literal_p = scanner_add_custom_literal (context_p,
                                                 scanner_context_p->active_literal_pool_p->prev_p,
                                                 &lexer_default_literal);

    name_literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
    scanner_context_p->active_literal_pool_p->no_declarations++;
  }
#endif  

  literal_pool_p->source_p = source_p;
  literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CLASS_NAME;

  parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR);
  scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;

  return literal_p;
}  