protected function parseSubkeys($key) {
        $k          = $key;
        $subkeys    = [];
        $quoteChars = ["'", '"'];                       // single and double quotes

        while (true) {
            $k = trim($k);

            foreach ($quoteChars as $char) {
                if (strpos($k, $char) === 0) {          // subkey starts with a quote char
                    $pos = strpos($k, $char, 1);        // find the ending quote char
                    if ($pos === false) throw new InvalidArgumentException('Invalid argument $key: '.$key);
                    $subkeys[] = substr($k, 1, $pos-1);
                    $k         = trim(substr($k, $pos+1));
                    if (!strlen($k))                    // last subkey or next char is a key separator
                        break 2;
                    if (strpos($k, '.') !== 0) throw new InvalidArgumentException('Invalid argument $key: '.$key);
                    $k = substr($k, 1);
                    continue 2;
                }
            }

            // key is not quoted
            $pos = strpos($k, '.');                     // find next key separator
            if ($pos === false) {
                $subkeys[] = $k;                        // last subkey
                break;
            }
            $subkeys[] = trim(substr($k, 0, $pos));
            $k         = substr($k, $pos+1);            // next subkey
        }
        return $subkeys;
    }