2

我正在尝试制作一个可以将@this 转换为“this”的阅读器宏。这是我目前拥有的:

(defun string-reader (stream char)
   (declare (ignore char))
   (format nil "\"~a\"" (read-line stream t nil t))   
)    
(set-macro-character #\@ #'string-reader )

问题是这需要我在@this 之后添加一个换行符。我也用 (read) 尝试过,但这只是返回变量 test,它尚未设置。我不能硬编码@符号后的字符数,因为我不知道会有多少。有没有什么办法解决这一问题?

编辑:是循环读取字符和窥视字符的唯一方法,直到我到达#)、#\space 或#\Newline?

4

1 回答 1

3

您可以尝试使用read,然后查看它返回的内容:

(defun string-reader (stream char)
   (declare (ignore char))
   (let ((this (let ((*readtable* (copy-readtable)))
                 (setf (readtable-case *readtable*) :preserve)
                 (read stream t nil t))))
     (etypecase this
       (string this)
       (symbol (symbol-name this)))))

(set-macro-character #\@ #'string-reader)

以上将允许@Thisand @"This",但不允许@333

这个版本只读取一个字符串,直到空格:

(defun read-as-string-until-whitespace (stream)
  (with-output-to-string (out-stream)
    (loop for next = (peek-char nil stream t nil t)
          until (member next '(#\space #\newline #\tab))
          do (write-char (read-char stream t nil t) out-stream))))

(defun string-reader (stream char)
   (declare (ignore char))
   (read-as-string-until-whitespace stream))

(set-macro-character #\@ #'string-reader)

例子:

CL-USER 21 > @this
"this"

CL-USER 22 > @42
"42"

CL-USER 23 > @FooBar
"FooBar"
于 2015-06-19T17:23:43.397 回答