parser_parse_class_fields (parser_context_t *context_p) /**< context */
{
  parser_saved_context_t saved_context;
  ecma_compiled_code_t *compiled_code_p;

  uint32_t extra_status_flags = context_p->status_flags & PARSER_INSIDE_WITH;

  parser_save_context (context_p, &saved_context);
  context_p->status_flags |= (PARSER_IS_FUNCTION
                              | PARSER_ALLOW_SUPER
                              | PARSER_INSIDE_CLASS_FIELD
                              | PARSER_ALLOW_NEW_TARGET
                              | extra_status_flags);

#if JERRY_PARSER_DUMP_BYTE_CODE
  if (context_p->is_show_opcodes)
  {
    JERRY_DEBUG_MSG ("\n--- Class fields parsing start ---\n\n");
  }
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */

#if JERRY_DEBUGGER
  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
  {
    jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
  }
#endif /* JERRY_DEBUGGER */

  const uint8_t *source_end_p = context_p->source_end_p;
  bool first_computed_class_field = true;
  scanner_location_t end_location;
  scanner_get_location (&end_location, context_p);

  do
  {
    uint8_t class_field_type = context_p->stack_top_uint8;
    parser_stack_pop_uint8 (context_p);

    scanner_range_t range = {0};

    if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
    {
      parser_stack_pop (context_p, &range, sizeof (scanner_range_t));
    }
    else if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
    {
      parser_stack_pop (context_p, &range.start_location, sizeof (scanner_location_t));
    }

    uint16_t literal_index = 0;

    if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
    {
      scanner_set_location (context_p, &range.start_location);
      context_p->source_end_p = source_end_p;
      scanner_seek (context_p);

      lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);

      literal_index = context_p->lit_object.index;

      if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
      {
        lexer_next_token (context_p);
        JERRY_ASSERT (context_p->token.type == LEXER_ASSIGN);
      }
    }
    else if (first_computed_class_field)
    {
      parser_emit_cbc (context_p, CBC_PUSH_NUMBER_0);
      first_computed_class_field = false;
    }

    if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
    {
      if (!(class_field_type & PARSER_CLASS_FIELD_NORMAL))
      {
        scanner_set_location (context_p, &range.start_location);
        scanner_seek (context_p);
      }

      context_p->source_end_p = range.source_end_p;
      lexer_next_token (context_p);

#if JERRY_LINE_INFO
      parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
#endif /* JERRY_LINE_INFO */

      parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);

      if (context_p->token.type != LEXER_EOS)
      {
        parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
      }
    }
    else
    {
      parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
    }

    if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
    {
      parser_emit_cbc_literal (context_p, CBC_ASSIGN_PROP_THIS_LITERAL, literal_index);

      /* Prepare stack slot for assignment property reference base. Needed by vm.c */
      if (context_p->stack_limit == context_p->stack_depth)
      {
        context_p->stack_limit++;
        JERRY_ASSERT (context_p->stack_limit <= PARSER_MAXIMUM_STACK_LIMIT);
      }
    }
    else
    {
      parser_flush_cbc (context_p);

      /* The next opcode pushes two more temporary values onto the stack */
      if (context_p->stack_depth + 1 > context_p->stack_limit)
      {
        context_p->stack_limit = (uint16_t) (context_p->stack_depth + 1);
        if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT)
        {
          parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
        }
      }

      parser_emit_cbc_ext (context_p, CBC_EXT_SET_NEXT_COMPUTED_FIELD);
    }
  }
  while (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_END));

  if (!first_computed_class_field)
  {
    parser_emit_cbc (context_p, CBC_POP);
  }

  parser_flush_cbc (context_p);
  context_p->source_end_p = source_end_p;
  scanner_set_location (context_p, &end_location);

#if JERRY_LINE_INFO
  if (context_p->line_info_p == NULL)
  {
    parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
  }
#endif /* JERRY_LINE_INFO */

  compiled_code_p = parser_post_processing (context_p);

#if JERRY_PARSER_DUMP_BYTE_CODE
  if (context_p->is_show_opcodes)
  {
    JERRY_DEBUG_MSG ("\n--- Class fields parsing end ---\n\n");
  }
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */

  parser_restore_context (context_p, &saved_context);

  return compiled_code_p;
} /* parser_parse_class_fields */
parser_parse_class_fields (parser_context_t *context_p)  
{
  parser_saved_context_t saved_context;
  ecma_compiled_code_t *compiled_code_p;

  uint32_t extra_status_flags = context_p->status_flags & PARSER_INSIDE_WITH;

  parser_save_context (context_p, &saved_context);
  context_p->status_flags |= (PARSER_IS_FUNCTION
                              | PARSER_ALLOW_SUPER
                              | PARSER_INSIDE_CLASS_FIELD
                              | PARSER_ALLOW_NEW_TARGET
                              | extra_status_flags);

#if JERRY_PARSER_DUMP_BYTE_CODE
  if (context_p->is_show_opcodes)
  {
    JERRY_DEBUG_MSG ("\n--- Class fields parsing start ---\n\n");
  }
#endif  

#if JERRY_DEBUGGER
  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
  {
    jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
  }
#endif  

  const uint8_t *source_end_p = context_p->source_end_p;
  bool first_computed_class_field = true;
  scanner_location_t end_location;
  scanner_get_location (&end_location, context_p);

  do
  {
    uint8_t class_field_type = context_p->stack_top_uint8;
    parser_stack_pop_uint8 (context_p);

    scanner_range_t range = {0};

    if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
    {
      parser_stack_pop (context_p, &range, sizeof (scanner_range_t));
    }
    else if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
    {
      parser_stack_pop (context_p, &range.start_location, sizeof (scanner_location_t));
    }

    uint16_t literal_index = 0;

    if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
    {
      scanner_set_location (context_p, &range.start_location);
      context_p->source_end_p = source_end_p;
      scanner_seek (context_p);

      lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);

      literal_index = context_p->lit_object.index;

      if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
      {
        lexer_next_token (context_p);
        JERRY_ASSERT (context_p->token.type == LEXER_ASSIGN);
      }
    }
    else if (first_computed_class_field)
    {
      parser_emit_cbc (context_p, CBC_PUSH_NUMBER_0);
      first_computed_class_field = false;
    }

    if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
    {
      if (!(class_field_type & PARSER_CLASS_FIELD_NORMAL))
      {
        scanner_set_location (context_p, &range.start_location);
        scanner_seek (context_p);
      }

      context_p->source_end_p = range.source_end_p;
      lexer_next_token (context_p);

#if JERRY_LINE_INFO
      parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
#endif  

      parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);

      if (context_p->token.type != LEXER_EOS)
      {
        parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
      }
    }
    else
    {
      parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
    }

    if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
    {
      parser_emit_cbc_literal (context_p, CBC_ASSIGN_PROP_THIS_LITERAL, literal_index);

       
      if (context_p->stack_limit == context_p->stack_depth)
      {
        context_p->stack_limit++;
        JERRY_ASSERT (context_p->stack_limit <= PARSER_MAXIMUM_STACK_LIMIT);
      }
    }
    else
    {
      parser_flush_cbc (context_p);

       
      if (context_p->stack_depth + 1 > context_p->stack_limit)
      {
        context_p->stack_limit = (uint16_t) (context_p->stack_depth + 1);
        if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT)
        {
          parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
        }
      }

      parser_emit_cbc_ext (context_p, CBC_EXT_SET_NEXT_COMPUTED_FIELD);
    }
  }
  while (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_END));

  if (!first_computed_class_field)
  {
    parser_emit_cbc (context_p, CBC_POP);
  }

  parser_flush_cbc (context_p);
  context_p->source_end_p = source_end_p;
  scanner_set_location (context_p, &end_location);

#if JERRY_LINE_INFO
  if (context_p->line_info_p == NULL)
  {
    parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
  }
#endif  

  compiled_code_p = parser_post_processing (context_p);

#if JERRY_PARSER_DUMP_BYTE_CODE
  if (context_p->is_show_opcodes)
  {
    JERRY_DEBUG_MSG ("\n--- Class fields parsing end ---\n\n");
  }
#endif  

  parser_restore_context (context_p, &saved_context);

  return compiled_code_p;
}  