1

I am trying to make a reader macro that would convert @this into "this". This is what I currently have:

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

The problem is that this requires that I put a newline after ever @this. I've also tried it with (read), but that just returns the variable test, which has not been set. I can't just hard-code the number of characters after the @ symbol, because I don't know how many there would be. Is there any way to fix this?

Edit: is the only way to do this to loop over read-char and peek-char, reading until I get to #),#\space, or #\Newline?

1 Answer 1

2

You can try to use read and then look at what it returns:

(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)

Above would allow @This and @"This", but not @333.

This version just reads a string until whitespace:

(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)

Example:

CL-USER 21 > @this
"this"

CL-USER 22 > @42
"42"

CL-USER 23 > @FooBar
"FooBar"
Sign up to request clarification or add additional context in comments.

2 Comments

Would it be possible to allow it to include numbers and colons?
@iHuman The second version accepts anything.. eg @;test => ";test".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.