public function parse($string)
    {
        global $matchedNotes;

        $keyPrefixLen = $this->keyPrefix ? strlen($this->keyPrefix) : 0;
        
        $data = array();
        $toDelete = [];
        $lines = preg_split('@\n@', $string, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);

        foreach ($lines as list($l, $offset)) {
            $len = strlen($l);
            $l = trim($l);
            $offset += $len - strlen($l);

            if ($l && $l[0] == '@') {
                $curDelete = trim($l);
                $l = substr($l, 1);
                $d = preg_split('/\s+/', $l, 2, PREG_SPLIT_OFFSET_CAPTURE);
                
                $key = $d[0][0];
                if ($this->keyPrefix) {
                    if (strpos($key, $this->keyPrefix)!==0)
                        continue;
                    $key = substr($key, $keyPrefixLen);
                }
                
                $key = preg_split(
                    "/(
                           \]\[
                        |  \[
                        |  \]\.   # when php style abuts dot notation (foo[a].b)
                        |  \]
                        |  \.)
                    /x", 
                    rtrim($key, ']')
                );
                
                if (isset($d[1])) {
                    $value = $d[1][0];
                }
                else {
                    $value = $this->defaultValue;
                }
                
                $current = &$data;
                $found = array();
                foreach ($key as $part) {
                    if ($current && !is_array($current)) {
                        throw new RewriteException("Key at path ".implode('.', $found)." already had non-array value, tried to set key $part");
                    }

                    if (!$found) {
                        if (in_array($part, $matchedNotes)) {
                            $toDelete[] = $curDelete;
                        }
                    }
                    
                    $found[] = $part;
                    
                    // if the last segment is empty, it means "@key[] value" or "@key. value" was used,
                    //  so we should just assign the next key
                    if ($part !== "")
                        $current = &$current[$part];
                    else
                        $current = &$current[];
                }
                
                if ($current === null)
                    $current = $value;
                elseif (!is_array($current))
                    $current = array($current, $value);
                else
                    $current[] = $value;
                
                unset($current);
            }
        }
        return [$data, $toDelete];
    }