Automattic\WooCommerce\Vendor\GraphQL\Language

Lexer::readStringprivateWC 1.0

Method of the class: Lexer{}

No Hooks.

Returns

null. Nothing (null).

Usage

// private - for code of main (parent) class only
$result = $this->readString( $line, $col, $prev ): Token;
$line(int) (required)
.
$col(int) (required)
.
$prev(Token) (required)
.

Lexer::readString() code WC 10.9.1

private function readString(int $line, int $col, Token $prev): Token
{
    $start = $this->position;

    // Skip leading quote and read first string char:
    [$char, $code, $bytes] = $this->moveStringCursor(1, 1)
        ->readChar();

    $chunk = '';
    $value = '';

    while (! in_array($code, [null, 10, 13], true)) { // not LineTerminator
        if ($code === 34) { // Closing Quote (")
            $value .= $chunk;

            // Skip quote
            $this->moveStringCursor(1, 1);

            return new Token(
                Token::STRING,
                $start,
                $this->position,
                $line,
                $col,
                $prev,
                $value
            );
        }

        $this->assertValidStringCharacterCode($code, $this->position);
        $this->moveStringCursor(1, $bytes);

        if ($code === 92) { // \
            $value .= $chunk;
            [, $code] = $this->readChar(true);

            switch ($code) {
                case 34:
                    $value .= '"';
                    break;
                case 47:
                    $value .= '/';
                    break;
                case 92:
                    $value .= '\\';
                    break;
                case 98:
                    $value .= chr(8); // \b (backspace)
                    break;
                case 102:
                    $value .= "\f";
                    break;
                case 110:
                    $value .= "\n";
                    break;
                case 114:
                    $value .= "\r";
                    break;
                case 116:
                    $value .= "\t";
                    break;
                case 117:
                    $position = $this->position;
                    [$hex] = $this->readChars(4);
                    if (preg_match('/[0-9a-fA-F]{4}/', $hex) !== 1) {
                        throw new SyntaxError($this->source, $position - 1, "Invalid character escape sequence: \\u{$hex}");
                    }

                    $code = hexdec($hex);
                    assert(is_int($code), 'Since only a single char is read');

                    // UTF-16 surrogate pair detection and handling.
                    $highOrderByte = $code >> 8;
                    if ($highOrderByte >= 0xD8 && $highOrderByte <= 0xDF) {
                        [$utf16Continuation] = $this->readChars(6);
                        if (preg_match('/^\\\u[0-9a-fA-F]{4}$/', $utf16Continuation) !== 1) {
                            throw new SyntaxError($this->source, $this->position - 5, 'Invalid UTF-16 trailing surrogate: ' . $utf16Continuation);
                        }

                        $surrogatePairHex = $hex . substr($utf16Continuation, 2, 4);
                        $value .= mb_convert_encoding(pack('H*', $surrogatePairHex), 'UTF-8', 'UTF-16');
                        break;
                    }

                    $this->assertValidStringCharacterCode($code, $position - 2);

                    $value .= Utils::chr($code);
                    break;
                    // null means EOF, will delegate to general handling of unterminated strings
                case null:
                    continue 2;
                default:
                    $chr = Utils::chr($code);
                    throw new SyntaxError($this->source, $this->position - 1, "Invalid character escape sequence: \\{$chr}");
            }

            $chunk = '';
        } else {
            $chunk .= $char;
        }

        [$char, $code, $bytes] = $this->readChar();
    }

    throw new SyntaxError($this->source, $this->position, 'Unterminated string.');
}