private function parser(string $data, callable $cast = null, string $delimiter = ','): \Generator
    {
        if ($data[0] !== '{' || \substr($data, -1) !== '}') {
            throw new ParseException("Missing opening or closing brackets");
        }

        $data = \ltrim(\substr($data, 1));

        do {
            if ($data === '') {
                throw new ParseException("Missing closing bracket");
            }

            if ($data[0] === '{') { // Array
                $parser = $this->parser($data, $cast, $delimiter);
                yield \iterator_to_array($parser);
                $data = $parser->getReturn();
                $end = $this->trim($data, 0, $delimiter);
                continue;
            }

            if ($data[0] === '"') { // Quoted value
                for ($position = 1; isset($data[$position]); ++$position) {
                    if ($data[$position] === '\\') {
                        ++$position; // Skip next character
                        continue;
                    }

                    if ($data[$position] === '"') {
                        break;
                    }
                }

                if (!isset($data[$position])) {
                    throw new ParseException("Could not find matching quote in quoted value");
                }

                $yield = \stripslashes(\substr($data, 1, $position - 1));

                $end = $this->trim($data, $position + 1, $delimiter);
            } else { // Unquoted value
                $position = 0;
                while (isset($data[$position]) && $data[$position] !== $delimiter && $data[$position] !== '}') {
                    ++$position;
                }

                $yield = \trim(\substr($data, 0, $position));

                $end = $this->trim($data, $position, $delimiter);

                if (\strcasecmp($yield, "NULL") === 0) { // Literal NULL is always unquoted.
                    yield null;
                    continue;
                }
            }

            yield $cast ? $cast($yield) : $yield;
        } while ($end !== '}');

        return $data;
    }
private function parser(string $data, callable $cast = null, string $delimiter = ','): \Generator
    {
        if ($data[0] !== '{' || \substr($data, -1) !== '}') {
            throw new ParseException("Missing opening or closing brackets");
        }

        $data = \ltrim(\substr($data, 1));

        do {
            if ($data === '') {
                throw new ParseException("Missing closing bracket");
            }

            if ($data[0] === '{') { // Array
                $parser = $this->parser($data, $cast, $delimiter);
                yield \iterator_to_array($parser);
                $data = $parser->getReturn();
                $end = $this->trim($data, 0, $delimiter);
                continue;
            }

            if ($data[0] === '"') { // Quoted value
                for ($position = 1; isset($data[$position]); ++$position) {
                    if ($data[$position] === '\\') {
                        ++$position; // Skip next character
                        continue;
                    }

                    if ($data[$position] === '"') {
                        break;
                    }
                }

                if (!isset($data[$position])) {
                    throw new ParseException("Could not find matching quote in quoted value");
                }

                $yield = \stripslashes(\substr($data, 1, $position - 1));

                $end = $this->trim($data, $position + 1, $delimiter);
            } else { // Unquoted value
                $position = 0;
                while (isset($data[$position]) && $data[$position] !== $delimiter && $data[$position] !== '}') {
                    ++$position;
                }

                $yield = \trim(\substr($data, 0, $position));

                $end = $this->trim($data, $position, $delimiter);

                if (\strcasecmp($yield, "NULL") === 0) { // Literal NULL is always unquoted.
                    yield null;
                    continue;
                }
            }

            yield $cast ? $cast($yield) : $yield;
        } while ($end !== '}');

        return $data;
    }
private function parser ( string $ data , callable $ cast = null , string $ delimiter = ',' ) : \ Generator { if ( $ data [ 0 ] !== '{' || \ substr ( $ data , - 1 ) !== '}' ) { throw new ParseException ( "Missing opening or closing brackets" ) ; } $ data = \ ltrim ( \ substr ( $ data , 1 ) ) ; do { if ( $ data === '' ) { throw new ParseException ( "Missing closing bracket" ) ; } if ( $ data [ 0 ] === '{' ) { // Array $ parser = $ this -> parser ( $ data , $ cast , $ delimiter ) ; yield \ iterator_to_array ( $ parser ) ; $ data = $ parser -> getReturn ( ) ; $ end = $ this -> trim ( $ data , 0 , $ delimiter ) ; continue ; } if ( $ data [ 0 ] === '"' ) { // Quoted value for ( $ position = 1 ; isset ( $ data [ $ position ] ) ; ++ $ position ) { if ( $ data [ $ position ] === '\\' ) { ++ $ position ; // Skip next character continue ; } if ( $ data [ $ position ] === '"' ) { break ; } } if ( ! isset ( $ data [ $ position ] ) ) { throw new ParseException ( "Could not find matching quote in quoted value" ) ; } $ yield = \ stripslashes ( \ substr ( $ data , 1 , $ position - 1 ) ) ; $ end = $ this -> trim ( $ data , $ position + 1 , $ delimiter ) ; } else { // Unquoted value $ position = 0 ; while ( isset ( $ data [ $ position ] ) && $ data [ $ position ] !== $ delimiter && $ data [ $ position ] !== '}' ) { ++ $ position ; } $ yield = \ trim ( \ substr ( $ data , 0 , $ position ) ) ; $ end = $ this -> trim ( $ data , $ position , $ delimiter ) ; if ( \ strcasecmp ( $ yield , "NULL" ) === 0 ) { // Literal NULL is always unquoted. yield null ; continue ; } } yield $ cast ? $ cast ( $ yield ) : $ yield ; } while ( $ end !== '}' ) ; return $ data ; }
Recursive generator parser yielding array values.

@param string $data Remaining buffer data.
@param callable|null $cast Callback to cast parsed values.
@param string $delimiter Delimiter used to separate values.

@return \Generator

@throws ParseException
Recursive generator parser yielding array values .