リーダーマクロを定義する:ダブルクォート型 - lisp-cookbook-ja/common-lisp GitHub Wiki

標準のリーダーマクロである「"」と同じタイプの例です。

(defun read-string (stream close-char)
  (with-output-to-string (out)
    (do ((char (read-char stream nil :eof) (read-char stream nil :eof)))
        ((or (eq char :eof) (char= char close-char))
         (if (eq char :eof)
             (error 'end-of-file :stream stream)))
      (when (char= #\\ char)
        (setq char (read-char stream nil :eof))
        (if (eq char :eof)
            (error 'end-of-file :stream stream)))
      (princ char out))))

リーダーがマクロ文字に遭遇すると、指定した終端の文字までを読み込み文字列として返します。

上記では、終端文字を文字列に含めるには、\でエスケープすることにしています。

;;; %〜%を文字列として読む
(let ((*readtable* (copy-readtable nil)))

  (set-macro-character #\% #'read-string)

  (with-input-from-string (in "%foo bar \\%baz%") (read in)))
;=>  "foo bar %baz"

;;; 「〜」を文字列として読む
(let ((*readtable* (copy-readtable nil)))

  (set-macro-character #\「 (lambda (s c) (read-string s #\」)))

  (with-input-from-string (in "「あいうえお かきくけこ「さしすせそ\\」」")
    (read in)))
;=>  "あいうえお かきくけこ「さしすせそ」"