public function stringValue(string $allowedNext = ',;)'): string
    {
        $value = '';

        if ($this->isEnd()) {
            throw $this->createSyntaxException('StringValue');
        }

        if ('"' === $this->data[$this->cursor]) {
            $this->moveCursor('"');

            while ("\n" !== $c = mb_substr($this->data, $this->char, 1)) {
                if ('"' === $c) {
                    if ($this->cursor + 1 === $this->end) {
                        break;
                    }
                    if ('"' !== mb_substr($this->data, $this->char + 1, 1)) {
                        break;
                    }

                    $this->moveCursor($c);
                }

                $value .= $c = mb_substr($this->data, $this->char, 1);
                $this->moveCursor($c);

                if ($this->cursor === $this->end) {
                    throw $this->createFormatException(StringLexerException::MISSING_END_QUOTE);
                }
            }

            if ("\n" === $c) {
                throw $this->createFormatException(StringLexerException::MISSING_END_QUOTE);
            }

            $this->moveCursor('"');

            $this->skipWhitespace();

            // Detect an user error like: "foo"bar"
            if ($this->cursor < $this->end && !$this->isGlimpse('/['.preg_quote($allowedNext, '/').']/A')) {
                throw $this->createFormatException(StringLexerException::VALUE_QUOTES_MUST_ESCAPE);
            }

            return $value;
        }

        $allowedNextRegex = '/['.preg_quote($allowedNext, '/').']/A';

        while ($this->cursor < $this->end && "\n" !== $c = mb_substr($this->data, $this->char, 1)) {
            if ('"' === $c) {
                throw $this->createFormatException(StringLexerException::QUOTED_VALUE_REQUIRE_QUOTING);
            }

            if ($this->isGlimpse($allowedNextRegex)) {
                break;
            }

            if ($this->isGlimpse('/[<>[\](),;~!*?=&*]/A')) {
                throw $this->createFormatException(StringLexerException::SPECIAL_CHARS_REQ_QUOTING);
            }

            $value .= $c;
            $this->moveCursor($c);
        }

        $value = rtrim($value);

        if (preg_match('/\s+/', $value)) {
            throw $this->createFormatException(StringLexerException::SPACES_REQ_QUOTING);
        }

        return $value;
    }