protected function parse()
    {
        $sectionName = static::GLOBAL_SECTION;
        $values = [];

        try {
            while ($line = fgets($this->handle)) {
                $this->linenumber++;
                $line = trim($line);
                if (empty($line) || substr($line, 0, 1) === ';') {
                    continue;
                }

                if ($this->isSectionHeader($line)) {
                    if ($sectionName === static::GLOBAL_SECTION) {
                        $this->config = $values;
                    } else {
                        $tokens = explode($this->delimiter, $sectionName);
                        $this->config = array_merge_recursive($this->config,
                                                              $this->subdivide($tokens, $values));

                        unset($tokens);
                    }

                    $sectionName = $this->getSectionHeader($line);
                    $values = [];
                    continue;
                }

                list($key, $value) = array_pad(preg_split(static::SPLIT_PATTERN, trim($line), 2), 2, '');

                if ($this->isArrayKey($key)) {
                    if (is_null($array_key = $this->parseArrayKey($key))) {
                        $key = trim(trim($key), '[]');

                        $values[$key][] = $this->parseValue($value);
                    } else {
                        $key = trim(substr($key, 0, strpos($key, '[')));
                        if (!isset($values[$key])) {
                            $values[$key] = [];
                        }

                        $values[$key][$array_key] = $this->parseValue($value);
                    }
                } else {
                    $values[trim($key)] = $this->parseValue($value);
                }
            }
        } catch (\Exception $ex) {
            throw new \RuntimeException("{$ex->getMessage()} Line: {$this->linenumber}.");
        } finally {
            $this->close();
        }

        if ($sectionName === static::GLOBAL_SECTION) {
            $this->config = $values;
        } else {
            $section = $this->subdivide(explode($this->delimiter, $sectionName), $values);
            $this->config = array_merge($this->config, $section);
        }
    }