parser_parse_var_statement (parser_context_t *context_p) /**< context */
{
  JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR
                || context_p->token.type == LEXER_KEYW_LET
                || context_p->token.type == LEXER_KEYW_CONST);

#if JERRY_ESNEXT
  uint8_t declaration_type = context_p->token.type;

  if (declaration_type != LEXER_KEYW_VAR)
  {
    parser_validate_lexical_context (context_p);
  }
#endif /* JERRY_ESNEXT */

  while (true)
  {
#if JERRY_ESNEXT
    if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE))
    {
      parser_pattern_flags_t flags = PARSER_PATTERN_BINDING;

      if (declaration_type == LEXER_KEYW_LET)
      {
        flags |= PARSER_PATTERN_LET;
      }
      else if (declaration_type == LEXER_KEYW_CONST)
      {
        flags |= PARSER_PATTERN_CONST;
      }

      parser_parse_initializer_by_next_char (context_p, flags);
    }
    else
    {
#endif /* JERRY_ESNEXT */
      lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL);
      JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
                    && context_p->token.lit_location.type == LEXER_IDENT_LITERAL);

#if JERRY_DEBUGGER || JERRY_LINE_INFO
      parser_line_counter_t ident_line_counter = context_p->token.line;
#endif /* JERRY_DEBUGGER || JERRY_LINE_INFO */
#if JERRY_LINE_INFO
      parser_line_counter_t ident_column_counter = context_p->token.column;
#endif /* JERRY_LINE_INFO */

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

#if JERRY_ESNEXT
      if (declaration_type != LEXER_KEYW_VAR
          && context_p->token.keyword_type == LEXER_KEYW_LET)
      {
        parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING);
      }

      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);
      }
#endif /* JERRY_ESNEXT */

      lexer_next_token (context_p);

      if (context_p->token.type == LEXER_ASSIGN)
      {
#if JERRY_DEBUGGER
        if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
            && ident_line_counter != context_p->last_breakpoint_line)
        {
          parser_emit_cbc (context_p, CBC_BREAKPOINT_DISABLED);
          parser_flush_cbc (context_p);

          parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST, ident_line_counter);

          context_p->last_breakpoint_line = ident_line_counter;
        }
#endif /* JERRY_DEBUGGER */

#if JERRY_LINE_INFO
        parser_line_info_append (context_p, ident_line_counter, ident_column_counter);
#endif /* JERRY_LINE_INFO */

        uint16_t index = context_p->lit_object.index;

        lexer_next_token (context_p);
        parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);

        cbc_opcode_t opcode = CBC_ASSIGN_SET_IDENT;

#if JERRY_ESNEXT
        uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p);

        if (function_literal_index == PARSER_ANONYMOUS_CLASS)
        {
          uint16_t name_index = scanner_save_literal (context_p, index);
          parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index);
        }
        else if (function_literal_index < PARSER_NAMED_FUNCTION)
        {
          parser_set_function_name (context_p, function_literal_index, index, 0);
        }

        if (declaration_type != LEXER_KEYW_VAR
            && (index < PARSER_REGISTER_START))
        {
          opcode = CBC_INIT_LET;

          if (scanner_literal_is_created (context_p, index))
          {
            opcode = CBC_ASSIGN_LET_CONST;
          }
          else if (declaration_type == LEXER_KEYW_CONST)
          {
            opcode = CBC_INIT_CONST;
          }
        }
#endif /* JERRY_ESNEXT */

        parser_emit_cbc_literal (context_p, (uint16_t) opcode, index);
      }
#if JERRY_ESNEXT
      else if (declaration_type == LEXER_KEYW_LET)
      {
        parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);

        uint16_t index = context_p->lit_object.index;
        cbc_opcode_t opcode = CBC_MOV_IDENT;

        if (index < PARSER_REGISTER_START)
        {
          opcode = (scanner_literal_is_created (context_p, index) ? CBC_ASSIGN_LET_CONST
                                                                  : CBC_INIT_LET);
        }

        parser_emit_cbc_literal (context_p, (uint16_t) opcode, index);
      }
      else if (declaration_type == LEXER_KEYW_CONST)
      {
        parser_raise_error (context_p, PARSER_ERR_MISSING_ASSIGN_AFTER_CONST);
      }
    }
#endif /* JERRY_ESNEXT */

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

#if JERRY_MODULE_SYSTEM
  context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT);
#endif /* JERRY_MODULE_SYSTEM */
} /* parser_parse_var_statement */