protected function lexString(int $line, int $column, Token $prev): Token
    {
        $start      = $this->position;
        $chunkStart = ++$this->position; // skip the quote
        $value      = '';

        while ($this->position < $this->bodyLength) {
            $code = $this->readCharCode($this->position);

            if (isLineTerminator($code)) {
                break;
            }

            // Closing Quote (")
            if (34 === $code) {
                $value .= sliceString($this->body, $chunkStart, $this->position);
                return new Token(TokenKindEnum::STRING, $start, $this->position + 1, $line, $column, $prev, $value);
            }

            if (isSourceCharacter($code)) {
                throw $this->createSyntaxErrorException(
                    \sprintf('Invalid character within String: %s.', printCharCode($code))
                );
            }

            ++$this->position;

            if (92 === $code) {
                // \
                $value .= sliceString($this->body, $chunkStart, $this->position - 1);

                $code = $this->readCharCode($this->position);

                switch ($code) {
                    case 34: // "
                        $value .= '"';
                        break;
                    case 47: // /
                        $value .= '/';
                        break;
                    case 92: // \
                        $value .= '\\';
                        break;
                    case 98: // b
                        $value .= '\b';
                        break;
                    case 102: // f
                        $value .= '\f';
                        break;
                    case 110: // n
                        $value .= '\n';
                        break;
                    case 114: // r
                        $value .= '\r';
                        break;
                    case 116: // t
                        $value .= '\t';
                        break;
                    case 117: // u
                        $unicodeString = sliceString($this->body, $this->position + 1, $this->position + 5);

                        if (!\preg_match('/[0-9A-Fa-f]{4}/', $unicodeString)) {
                            throw $this->createSyntaxErrorException(
                                \sprintf('Invalid character escape sequence: \\u%s.', $unicodeString)
                            );
                        }

                        $value .= '\\u' . $unicodeString;

                        $this->position += 4;

                        break;
                    default:
                        throw $this->createSyntaxErrorException(
                            \sprintf('Invalid character escape sequence: \\%s.', \chr($code))
                        );
                }

                ++$this->position;

                $chunkStart = $this->position;
            }
        }

        throw $this->createSyntaxErrorException('Unterminated string.');
    }