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

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

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

        while ($code !== null &&
            // not LineTerminator
            $code !== 10 && $code !== 13
        ) {
            // Closing Quote (")
            if ($code === 34) {
                $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);
                        break; // \b (backspace)
                    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, true);
                        if (! preg_match('/[0-9a-fA-F]{4}/', $hex)) {
                            throw new SyntaxError(
                                $this->source,
                                $position - 1,
                                'Invalid character escape sequence: \\u' . $hex
                            );
                        }
                        $code = hexdec($hex);
                        $this->assertValidStringCharacterCode($code, $position - 2);
                        $value .= Utils::chr($code);
                        break;
                    default:
                        throw new SyntaxError(
                            $this->source,
                            $this->position - 1,
                            'Invalid character escape sequence: \\' . Utils::chr($code)
                        );
                }
                $chunk = '';
            } else {
                $chunk .= $char;
            }

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

        throw new SyntaxError(
            $this->source,
            $this->position,
            'Unterminated string.'
        );
    }
private function readString($line, $col, Token $prev)
    {
        $start = $this->position;

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

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

        while ($code !== null &&
            
            $code !== 10 && $code !== 13
        ) {
            
            if ($code === 34) {
                $value .= $chunk;

                
                $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);
                        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, true);
                        if (! preg_match('/[0-9a-fA-F]{4}/', $hex)) {
                            throw new SyntaxError(
                                $this->source,
                                $position - 1,
                                'Invalid character escape sequence: \\u' . $hex
                            );
                        }
                        $code = hexdec($hex);
                        $this->assertValidStringCharacterCode($code, $position - 2);
                        $value .= Utils::chr($code);
                        break;
                    default:
                        throw new SyntaxError(
                            $this->source,
                            $this->position - 1,
                            'Invalid character escape sequence: \\' . Utils::chr($code)
                        );
                }
                $chunk = '';
            } else {
                $chunk .= $char;
            }

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

        throw new SyntaxError(
            $this->source,
            $this->position,
            'Unterminated string.'
        );
    }
private function readString ( $ line , $ col , Token $ prev ) { $ start = $ this -> position ; // Skip leading quote and read first string char: [ $ char , $ code , $ bytes ] = $ this -> moveStringCursor ( 1 , 1 ) -> readChar ( ) ; $ chunk = '' ; $ value = '' ; while ( $ code !== null && // not LineTerminator $ code !== 10 && $ code !== 13 ) { // Closing Quote (") if ( $ code === 34 ) { $ 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 ) ; break ; // \b (backspace) 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 , true ) ; if ( ! preg_match ( '/[0-9a-fA-F]{4}/' , $ hex ) ) { throw new SyntaxError ( $ this -> source , $ position - 1 , 'Invalid character escape sequence: \\u' . $ hex ) ; } $ code = hexdec ( $ hex ) ; $ this -> assertValidStringCharacterCode ( $ code , $ position - 2 ) ; $ value .= Utils :: chr ( $ code ) ; break ; default : throw new SyntaxError ( $ this -> source , $ this -> position - 1 , 'Invalid character escape sequence: \\' . Utils :: chr ( $ code ) ) ; } $ chunk = '' ; } else { $ chunk .= $ char ; } [ $ char , $ code , $ bytes ] = $ this -> readChar ( ) ; } throw new SyntaxError ( $ this -> source , $ this -> position , 'Unterminated string.' ) ; }
@param int $line
@param int $col

@return Token

@throws SyntaxError
@param int $line @param int $col