private function readString($start, $line, $col, Token $prev)
{
$body = $this->source->body;
$bodyLength = $this->source->length;
$position = $start + 1;
$chunkStart = $position;
$code = null;
$value = '';
while ($position < $bodyLength && ($code = Utils::charCodeAt($body, $position)) && $code !== 0xa && $code !== 0xd && $code !== 34) {
$this->assertValidStringCharacterCode($code, $position);
++$position;
if ($code === 92) {
// \
$value .= mb_substr($body, $chunkStart, $position - 1 - $chunkStart, 'UTF-8');
$code = Utils::charCodeAt($body, $position);
switch ($code) {
case 34:
$value .= '"';
break;
case 47:
$value .= '/';
break;
case 92:
$value .= '\\';
break;
case 98:
$value .= chr(8);
break;
// \b (backspace)
// \b (backspace)
case 102:
$value .= "\f";
break;
case 110:
$value .= "\n";
break;
case 114:
$value .= "\r";
break;
case 116:
$value .= "\t";
break;
case 117:
$hex = mb_substr($body, $position + 1, 4, 'UTF-8');
if (!preg_match('/[0-9a-fA-F]{4}/', $hex)) {
throw new SyntaxError($this->source, $position, 'Invalid character escape sequence: \\u' . $hex);
}
$code = hexdec($hex);
$this->assertValidStringCharacterCode($code, $position - 1);
$value .= Utils::chr($code);
$position += 4;
break;
default:
throw new SyntaxError($this->source, $position, 'Invalid character escape sequence: \\' . Utils::chr($code));
}
++$position;
$chunkStart = $position;
}
}
if ($code !== 34) {
throw new SyntaxError($this->source, $position, 'Unterminated string.');
}
$value .= mb_substr($body, $chunkStart, $position - $chunkStart, 'UTF-8');
return new Token(Token::STRING, $start, $position + 1, $line, $col, $prev, $value);
}