(defstruct (readtable (:predicate readtablep) (:copier nil))
(syntax (make-hash-table) :type hash-table)
(case :upcase :type (member :upcase :downcase :preserve :invert)))
(defvar *read-base* '10)
(defvar *read-default-float-format* 'single-float)
(defvar *read-eval* 't)
(defvar *read-suppress* 'nil)
(defvar *readtable*)
(defvar *sharp-equal-alist* nil)
(defvar *consing-dot-allowed* nil)
(defvar *consing-dot* (gensym))
(defvar *preserve-whitespace-p* nil)
(defvar *input-stream* nil)
(defvar *backquote-level* 0)
(defvar *dispatch-macro-char* nil)
(defvar *standard-readtable*)
(define-condition reader-error (parse-error)
((format-control :reader reader-error-format-control :initarg :format-control)
(format-arguments :reader reader-error-format-arguments
:initarg :format-arguments)))
(define-condition invalid-character-error (reader-error)
((character :type character :reader invalid-character-error-character
:initarg :character))
(:report
(lambda (condition stream)
(format stream "Invalid character ~S is read."
(invalid-character-error-character condition)))))
(defun reader-error (&optional format-control &rest format-arguments)
(error 'reader-error
:format-control format-control :format-arguments format-arguments))
(defun copy-readtable (&optional (from-readtable *readtable*) to-readtable)
(flet ((copy-syntax (src)
(let ((new (make-hash-table)))
(maphash
#'(lambda (k v)
(let ((plist (copy-list v)))
(setf (gethash k new) plist)
(when (getf plist :dispatch-table)
(let ((hash (make-hash-table)))
(maphash #'(lambda (k v) (setf (gethash k hash) v))
(getf plist :dispatch-table))
(setf (getf plist :dispatch-table) hash)))))
src)
new)))
(let ((from (or from-readtable *standard-readtable*)))
(if to-readtable
(prog1 to-readtable
(setf (readtable-syntax to-readtable)
(copy-syntax (readtable-syntax from)))
(setf (readtable-case to-readtable) (readtable-case from)))
(make-readtable :syntax (copy-syntax (readtable-syntax from))
:case (readtable-case from))))))
(defun syntax-type (char &optional (readtable *readtable*))
(let ((plist (gethash char (readtable-syntax readtable))))
(getf plist :syntax :constituent)))
(defun get-macro-character (char &optional (readtable *readtable*))
(unless readtable (setq readtable *standard-readtable*))
(let ((plist (gethash char (readtable-syntax readtable))))
(case (syntax-type char readtable)
(:terminating-macro-char (values (getf plist :macro-function) nil))
(:non-terminating-macro-char (values (getf plist :macro-function) t))
(t (values nil nil)))))
(defun set-macro-character (char new-function
&optional non-terminating-p (readtable *readtable*))
(check-type char character)
(check-type new-function function-designator)
(when (null readtable)
(error "Standard readtable must not be changed."))
(let ((plist (gethash char (readtable-syntax readtable))))
(setf (getf plist :syntax) (if non-terminating-p
:non-terminating-macro-char
:terminating-macro-char)
(getf plist :macro-function) new-function
(gethash char (readtable-syntax readtable)) plist))
t)
(defun get-dispatch-macro-character (disp-char sub-char
&optional (readtable *readtable*))
(unless readtable (setq readtable *standard-readtable*))
(unless (eq (get-macro-character disp-char readtable)
'dispatch-macro-character)
(error "~S is not a dispatching macro character." disp-char))
(let* ((syntax-table (readtable-syntax readtable))
(dispatch-table (getf (gethash disp-char syntax-table) :dispatch-table))
(sub-char (char-upcase sub-char)))
(multiple-value-bind (value present-p) (gethash sub-char dispatch-table)
(cond
((digit-char-p sub-char 10) nil)
(present-p value)
(t
#'(lambda (stream sub-char number)
(declare (ignore stream number))
(reader-error "No dispatch function defined for ~S." sub-char)))))))
(defun set-dispatch-macro-character (disp-char sub-char new-function
&optional (readtable *readtable*))
(when (null readtable) (error "Standard readtable must not be changed."))
(unless (eq (get-macro-character disp-char readtable)
'dispatch-macro-character)
(error "~S is not a dispatch character." disp-char))
(let* ((syntax-table (readtable-syntax readtable))
(dispatch-table (getf (gethash disp-char syntax-table) :dispatch-table))
(sub-char (char-upcase sub-char)))
(setf (gethash sub-char dispatch-table) new-function)
t))
(defun make-dispatch-macro-character (char &optional non-terminating-p
(readtable *readtable*))
(when (null readtable) (error "Standard readtable must not be changed."))
(set-macro-character char 'dispatch-macro-character
non-terminating-p readtable)
(setf (getf (gethash char (readtable-syntax readtable)) :dispatch-table)
(make-hash-table))
t)
(defun dispatch-macro-character (stream char)
(let ((n (when (digit-char-p (peek-char nil stream t nil t) 10)
(loop
with n = 0
for digit = (read-char stream t nil t)
do (setq n (+ (* n 10) (digit-char-p digit 10)))
while (digit-char-p (peek-char nil stream t nil t) 10)
finally (return n))))
(*dispatch-macro-char* char)
(sub-char (char-upcase (read-char stream t nil t))))
(funcall (get-dispatch-macro-character char sub-char) stream sub-char n)))
(defun set-syntax-from-char (to-char from-char
&optional (to-readtable *readtable*)
(from-readtable *standard-readtable*))
(check-type to-char character)
(check-type from-char character)
(check-type to-readtable readtable)
(unless from-readtable (setq from-readtable *standard-readtable*))
(check-type from-readtable readtable)
(let ((plist (copy-list (gethash from-char
(readtable-syntax from-readtable)))))
(when (getf plist :dispatch-table)
(let ((hash (make-hash-table)))
(maphash #'(lambda (k v) (setf (gethash k hash) v))
(getf plist :dispatch-table))
(setf (getf plist :dispatch-table) hash)))
(setf (gethash to-char (readtable-syntax to-readtable)) plist)
t))
(defun read-preserving-whitespace (&optional (input-stream *standard-input*)
(eof-error-p t) eof-value recursive-p)
(let ((*preserve-whitespace-p* (if recursive-p *preserve-whitespace-p* t)))
(declare (special *preserve-whitespace-p*))
(read-lisp-object input-stream eof-error-p eof-value recursive-p)))
(defun read (&optional (input-stream *standard-input*)
(eof-error-p t) eof-value recursive-p)
(let ((*preserve-whitespace-p* (when recursive-p *preserve-whitespace-p*)))
(declare (special *preserve-whitespace-p*))
(read-lisp-object input-stream eof-error-p eof-value recursive-p)))
(defun read-from-string (string &optional (eof-error-p t) eof-value
&key (start 0) end preserve-whitespace)
(let ((index nil))
(values (with-input-from-string (stream string :index index
:start start :end end)
(funcall (if preserve-whitespace
#'read-preserving-whitespace
#'read)
stream eof-error-p eof-value))
index)))
(defun make-str (chars)
(make-array (length chars) :element-type 'character :initial-contents chars))
(defun read-list (char &optional (stream *standard-input*) recursive-p
&key allow-consing-dot)
(let ((*sharp-equal-alist* (when recursive-p *sharp-equal-alist*))
(*consing-dot-allowed* allow-consing-dot)
c stack values)
(loop
(setq c (peek-char t stream t nil t))
(when (char= char c)
(when (eq (first stack) *consing-dot*)
(error "Nothing appears after . in list."))
(read-char stream t nil t)
(if (eq (second stack) *consing-dot*)
(return (nreconc (cddr stack) (first stack)))
(return (nreverse stack))))
(when (setq values (multiple-value-list (lisp-object? stream t nil t)))
(if (eq (second stack) *consing-dot*)
(error "More than one object follows . in list.")
(push (car values) stack))))))
(defun read-delimited-list (char &optional (stream *standard-input*) recursive-p)
(let ((list (read-list char stream recursive-p)))
(unless *read-suppress* list)))
(defun lisp-object? (stream eof-error-p eof-value recursive-p)
(loop
(let* ((c (read-char stream eof-error-p eof-value recursive-p)))
(when (and (not eof-error-p) (eq c eof-value)) (return eof-value))
(ecase (syntax-type c)
(:invalid (error 'invalid-character-error :character c))
(:whitespace 'skip)
((:single-escape :multiple-escape :constituent)
(return (read-number-or-symbol stream c)))
((:terminating-macro-char :non-terminating-macro-char)
(return (funcall (get-macro-character c) stream c)))))))
(defun read-lisp-object (stream eof-error-p eof-value recursive-p)
(let ((*sharp-equal-alist* (when recursive-p *sharp-equal-alist*)))
(loop
(let ((values (multiple-value-list (lisp-object? stream
eof-error-p eof-value
recursive-p))))
(when values (return (unless *read-suppress* (car values))))))))
(defun read-ch () (read-char *input-stream* nil nil t))
(defun read-ch-or-die () (read-char *input-stream* t nil t))
(defun unread-ch (c) (unread-char c *input-stream*))
(defun collect-escaped-lexemes (c)
(ecase (syntax-type c)
(:invalid (error 'invalid-character-error :character c))
(:multiple-escape nil)
(:single-escape (cons (read-ch-or-die)
(collect-escaped-lexemes (read-ch-or-die))))
((:constituent
:whitespace :terminating-macro-char :non-terminating-macro-char)
(cons c (collect-escaped-lexemes (read-ch-or-die))))))
(defun collect-lexemes (c &optional (stream *input-stream*))
(let ((*input-stream* stream))
(when c
(ecase (syntax-type c)
(:invalid (error 'invalid-character-error :character c))
(:whitespace (when *preserve-whitespace-p* (unread-ch c)))
(:terminating-macro-char (unread-ch c))
(:multiple-escape (cons (collect-escaped-lexemes (read-ch-or-die))
(collect-lexemes (read-ch))))
(:single-escape (cons (list (read-ch-or-die))
(collect-lexemes (read-ch))))
((:constituent :non-terminating-macro-char)
(cons c (collect-lexemes (read-ch))))))))
(defun construct-number (chars)
(labels ((sign ()
(let ((c (and chars (car chars))))
(cond
((eql c #\-) (pop chars) -1)
((eql c #\+) (pop chars) +1)
(t +1))))
(digit* (&optional (base *read-base*))
(let ((pos (or (position-if-not #'(lambda (d) (digit-char-p d base))
chars)
(length chars))))
(prog1 (subseq chars 0 pos)
(setq chars (subseq chars pos)))))
(int? (sign digits &optional (base *read-base*))
(when (and digits
(every #'(lambda (d) (digit-char-p d base)) digits))
(* sign (reduce #'(lambda (a b) (+ (* base a) b))
(mapcar #'(lambda (d) (digit-char-p d base))
digits)))))
(float? (sign)
(let* ((int (digit* 10))
(fraction (when (eql (car chars) #\.)
(pop chars) (digit* 10)))
(exp-marker (when (and chars
(find (char-upcase (car chars))
'(#\D #\E #\F #\L #\S)))
(char-upcase (pop chars))))
(exp-sign (and exp-marker (sign)))
(exp-digits (and exp-sign (digit*))))
(when (and (null chars)
(or fraction (and int exp-marker exp-digits)))
(float (* (int? sign (append int fraction) 10)
(expt 10 (- (or (int? exp-sign exp-digits 10) 0)
(length fraction))))
(ecase (or exp-marker *read-default-float-format*)
(#\E 1.0e0)
((#\D double-float) 1.0d0)
((#\F single-float) 1.0f0)
((#\L long-float) 1.0l0)
((#\S short-float) 1.0s0)))))))
(let ((sign (sign))
pos numerator denominator)
(when chars
(or
(int? sign chars)
(and (eql (car (last chars)) #\.) (int? sign (butlast chars) 10))
(and (setq pos (position #\/ chars))
(setq numerator (int? sign (subseq chars 0 pos)))
(setq denominator (int? 1 (subseq chars (1+ pos))))
(not (zerop denominator))
(/ numerator denominator))
(float? sign))))))
(defun ensure-external-symbol (name package)
(multiple-value-bind (symbol status) (find-symbol name package)
(unless (eq status :external)
(cerror (if (null status)
"Intern and export symbol ~S in package ~S."
"Export symbol ~S in package ~S.")
"There is no external symbol by the name of ~S in package ~S."
name package)
(export (setq symbol (intern name package)) package))
symbol))
(defun construct-symbol (lexemes &key uninterned-symbol-wanted)
(labels ((up (x) (if (listp x) (copy-list x) (list (char-upcase x))))
(down (x) (if (listp x) (copy-list x) (list (char-downcase x))))
(chars (lexemes)
(ecase (readtable-case *readtable*)
(:upcase (mapcan #'up lexemes))
(:downcase (mapcan #'down lexemes))
(:invert
(let ((unescaped (remove-if-not #'alpha-char-p
(remove-if #'listp lexemes))))
(mapcan (cond
((every #'upper-case-p unescaped) #'down)
((every #'lower-case-p unescaped) #'up)
(t #'(lambda (x)
(if (listp x) (copy-list x) (list x)))))
lexemes)))
(:preserve (mapcan #'(lambda (x)
(if (listp x) (copy-list x) (list x)))
lexemes))))
(name (lexemes)
(when (find #\: lexemes) (error "Too many package markers."))
(make-str (chars lexemes))))
(let* ((pos (position #\: lexemes))
(external-p (and pos (not (eql (nth (1+ pos) lexemes) #\:))))
(package (when pos (name (subseq lexemes 0 pos))))
(name (name (subseq lexemes (if pos (+ pos (if external-p 1 2)) 0)))))
(values (cond
(uninterned-symbol-wanted
(if package
(reader-error)
(make-symbol name)))
(external-p
(ensure-external-symbol name package))
(t (intern name (or package *package*))))))))
(defun read-number-or-symbol (stream c)
(let ((lexemes (collect-lexemes c stream)))
(assert lexemes)
(unless *read-suppress*
(cond
((and lexemes (every #'(lambda (x) (eql x #\.)) lexemes))
(when (rest lexemes)
(reader-error "Tokens consisting of only dots are invalid."))
(when (not *consing-dot-allowed*)
(reader-error "Consing dot is not allowed."))
*consing-dot*)
(t
(or (and (every #'characterp lexemes) (construct-number lexemes))
(construct-symbol lexemes)))))))
(defconstant backquote (gensym))
(defconstant backquote-comma (gensym))
(defconstant backquote-comma-at (gensym))
(defconstant backquote-comma-dot (gensym))
(defun backquoted-expression-type (exp)
(if (atom exp)
:normal
(cond
((eq (first exp) backquote-comma) :comma)
((eq (first exp) backquote-comma-at) :comma-at)
((eq (first exp) backquote-comma-dot) :comma-dot)
(t :normal))))
(defmacro backquote (object)
(if (atom object)
(if (simple-vector-p object)
(list 'apply #'vector (list backquote (concatenate 'list object)))
(list 'quote object))
(let* ((list (copy-list object))
(last (loop for x = list then (cdr x)
until (or (atom (cdr x))
(find (cadr x) (list backquote
backquote-comma
backquote-comma-at
backquote-comma-dot)))
finally (return (prog1 (cdr x) (setf (cdr x) nil)))))
(types (mapcar #'backquoted-expression-type list)))
(append
(cons (if (notany #'(lambda (x) (eq x :comma-at)) types) 'nconc 'append)
(mapcar #'(lambda (x)
(ecase (backquoted-expression-type x)
(:normal (list 'list (list 'backquote x)))
(:comma (list 'list x))
((:comma-at :comma-dot) x)))
list))
(list (ecase (backquoted-expression-type last)
(:normal (list 'quote last))
(:comma last)
(:comma-at (error ",@ after dot"))
(:comma-dot (error ",. after dot"))))))))
(defmacro backquote-comma (obj) obj)
(setf (macro-function backquote) (macro-function 'backquote))
(setf (macro-function backquote-comma) (macro-function 'backquote-comma))
(setf (macro-function backquote-comma-at) (macro-function 'backquote-comma))
(setf (macro-function backquote-comma-dot) (macro-function 'backquote-comma))
(defun read-comma-form (stream c)
(declare (ignore c))
(unless (> *backquote-level* 0)
(error "Comma must be used in a backquoted expression."))
(let ((*backquote-level* (1- *backquote-level*)))
(case (peek-char t stream t nil t)
(#\@ (read-char stream t nil t)
(list backquote-comma-at (read stream t nil t)))
(#\. (read-char stream t nil t)
(list backquote-comma-dot (read stream t nil t)))
(t (list backquote-comma (read stream t nil t))))))
(defun read-backquoted-expression (stream c)
(declare (ignore c))
(let ((*backquote-level* (1+ *backquote-level*)))
(list backquote (read stream t nil t))))
(defun sharp-backslash (stream sub-char n)
(declare (ignore n))
(let* ((lexemes (collect-lexemes sub-char stream))
(str (make-str (mapcan #'(lambda (x)
(if (listp x) (copy-list x) (list x)))
lexemes))))
(unless *read-suppress*
(cond
((= 1 (length str)) (char str 0))
((name-char str))
(t (reader-error "Unrecognized character name: ~S" str))))))
(defun sharp-single-quote (stream sub-char n)
(declare (ignore sub-char n))
`(function ,(read stream t nil t)))
(defun sharp-left-parenthesis (stream sub-char n)
(declare (ignore sub-char))
(let ((list (read-delimited-list #\) stream t)))
(unless *read-suppress*
(when (and n (> (length list) n))
(reader-error "vector is longer than specified length #~A*~A."
n list))
(apply #'vector
(if (and n (< (length list) n))
(append list (make-list (- n (length list))
:initial-element (car (last list))))
list)))))
(defun sharp-asterisk (stream sub-char n)
(declare (ignore sub-char))
(let* ((*input-stream* stream)
(lexemes (collect-lexemes (read-ch)))
(bits (mapcar #'(lambda (d)
(unless (characterp d)
(error "Binary digit must be given"))
(digit-char-p d 2)) lexemes)))
(unless *read-suppress*
(unless (every #'(lambda (d) (digit-char-p d 2)) lexemes)
(reader-error "Illegal bit vector format."))
(when (and n (> (length bits) n))
(reader-error "Bit vector is longer than specified length #~A*~A."
n (make-str lexemes)))
(when (and n (> n 0) (zerop (length bits)))
(reader-error
"At least one bit must be given for non-zero #* bit-vectors."))
(make-array (or n (length bits)) :element-type 'bit
:initial-contents
(if (and n (< (length bits) n))
(append bits
(make-list (- n (length bits))
:initial-element (car (last bits))))
bits)))))
(defun sharp-colon (stream sub-char n)
(declare (ignore sub-char n))
(let* ((*input-stream* stream)
(lexemes (collect-lexemes (read-ch))))
(unless *read-suppress*
(construct-symbol lexemes :uninterned-symbol-wanted t))))
(defun sharp-dot (stream sub-char n)
(declare (ignore sub-char n))
(let ((object (read stream t nil t)))
(unless *read-suppress*
(unless *read-eval*
(reader-error "Attempt to read #. while *READ-EVAL* is bound to NIL."))
(eval object))))
(defun sharp-b (stream sub-char n)
(declare (ignore n))
(sharp-r stream sub-char 2))
(defun sharp-o (stream sub-char n)
(declare (ignore n))
(sharp-r stream sub-char 8))
(defun sharp-x (stream sub-char n)
(declare (ignore n))
(sharp-r stream sub-char 16))
(defun sharp-r (stream sub-char n)
(cond
(*read-suppress* (read stream t nil t))
((not n) (reader-error "Radix missing in #R."))
((not (<= 2 n 36)) (reader-error "Illegal radix for #R: ~D." n))
(t (let ((rational (let ((*read-base* n)) (read stream t nil t))))
(unless (typep rational 'rational)
(reader-error "#~A (base ~D) value is not a rational: ~S."
sub-char n rational))
rational))))
(defun sharp-c (stream sub-char n)
(declare (ignore sub-char n))
(let ((pair (read stream t nil t)))
(unless *read-suppress*
(unless (and (listp pair) (= (length pair) 2))
(reader-error "Illegal complex number format: #C~S" pair))
(complex (first pair) (second pair)))))
(defun sharp-a (stream sub-char rank)
(declare (ignore sub-char))
(cond
(*read-suppress* (read stream t nil t))
((null rank)
(reader-error "Rank for #A notation is missing."))
(t (let* ((contents (read stream t nil t))
(dimensions (loop repeat rank
for x = contents then (first x)
collect (length x))))
(make-array dimensions :initial-contents contents)))))
(defun find-default-constructor (name)
(declare (ignore name)))
(defun sharp-s (stream sub-char n)
(declare (ignore sub-char n))
(let ((structure-spec (read stream t nil t)))
(unless *read-suppress*
(unless (listp structure-spec)
(reader-error "Non list follows #S."))
(unless (symbolp (first structure-spec))
(reader-error "Structure type is not a symbol: ~S" (car structure-spec)))
(let* ((name (first structure-spec))
(plist (loop
for list on (rest structure-spec) by #'cddr
append (list (intern (string (first list)) "KEYWORD")
(second list))))
(class (find-class name nil)))
(unless (typep class 'structure-class)
(reader-error "~S is not a defined structure type." name))
(let ((constructor (find-default-constructor name)))
(apply constructor plist))))))
(defun sharp-p (stream sub-char n)
(declare (ignore sub-char n))
(let ((namestring (read stream t nil t)))
(unless *read-suppress* (parse-namestring namestring))))
(defun container-subst (new old tree
&optional (done (make-hash-table :test 'eq)))
(cond
((eq tree old) new)
((gethash tree done) tree)
(t (setf (gethash tree done) t)
(typecase tree
(null nil)
(cons (setf (car tree) (container-subst new old (car tree) done)
(cdr tree) (container-subst new old (cdr tree) done))
tree)
(array (loop for i below (array-total-size tree)
do (setf (row-major-aref tree i)
(container-subst new old
(row-major-aref tree i) done)))
tree)
(t tree)))))
(defun sharp-equal (stream sub-char n)
(declare (ignore sub-char))
(if *read-suppress*
(values)
(let* ((this (gensym))
(object (let ((*sharp-equal-alist* (acons n this
*sharp-equal-alist*)))
(read stream t nil t)))
(assoc (assoc n *sharp-equal-alist*)))
(when (null n)
(reader-error "Missing label number for #=."))
(when assoc
(reader-error "#~D= is already defined." n))
(setq *sharp-equal-alist* (acons n object *sharp-equal-alist*))
(when (eq object this)
(reader-error "need to tag something more than just #~D#." n))
(container-subst object this object))))
(defun sharp-sharp (stream sub-char n)
(declare (ignore sub-char stream))
(unless *read-suppress*
(unless n (reader-error "Label is missing for ##."))
(let ((assoc (assoc n *sharp-equal-alist*)))
(unless assoc
(reader-error "No object labeld ~D is defined." n))
(cdr assoc))))
(defun featurep (x)
(if (atom x)
(member x *features*)
(ecase (first x)
(:not (not (featurep (second x))))
(:and (every #'featurep (rest x)))
(:or (some #'featurep (rest x))))))
(defun read-feature-test (stream)
(let ((*package* (or (find-package "KEYWORD")
(error "KEYWORD package not found."))))
(read stream t nil t)))
(defun sharp-plus (stream sub-char n)
(declare (ignore sub-char n))
(if (featurep (read-feature-test stream))
(read stream t nil t)
(let ((*read-suppress* t)) (read stream t nil t) (values))))
(defun sharp-minus (stream sub-char n)
(declare (ignore sub-char n))
(if (not (featurep (read-feature-test stream)))
(read stream t nil t)
(let ((*read-suppress* t)) (read stream t nil t) (values))))
(defun sharp-vertical-bar (stream sub-char n)
(declare (ignore sub-char n))
(loop for c = (read-char stream t nil t)
if (and (char= c #\#) (char= (read-char stream t nil t) #\|))
do (sharp-vertical-bar stream #\| nil)
until (and (char= c #\|) (char= (read-char stream t nil t) #\#)))
(values))
(defvar *standard-syntax-table*
(let ((table (make-hash-table)))
(mapc #'(lambda (x)
(let ((syntax (first x))
(chars (rest x)))
(dolist (c chars)
(setf (gethash c table) `(:syntax ,syntax)))))
'((:whitespace #\Tab #\Newline #\Linefeed #\Page #\Return #\Space)
(:single-escape #\\)
(:multiple-escape #\|)))
table))
(setq *standard-readtable* (make-readtable :syntax *standard-syntax-table*))
(set-macro-character #\` 'read-backquoted-expression nil *standard-readtable*)
(set-macro-character #\, 'read-comma-form nil *standard-readtable*)
(set-macro-character #\( #'(lambda (stream char)
(declare (ignore char))
(read-list #\) stream t :allow-consing-dot t))
nil *standard-readtable*)
(set-macro-character #\) #'(lambda (stream char)
(declare (ignore stream char))
(error "Unmatched close parenthesis."))
nil *standard-readtable*)
(set-macro-character #\' #'(lambda (stream char)
(declare (ignore char))
`(quote ,(read stream t nil t)))
nil *standard-readtable*)
(set-macro-character #\; #'(lambda (stream char)
(declare (ignore char))
(loop
for c = (read-char stream nil nil t)
until (or (null c) (eql c #\Newline)))
(values))
nil *standard-readtable*)
(set-macro-character #\" #'(lambda (stream char)
(declare (ignore char))
(loop
for c = (read-char stream t nil t)
until (char= c #\")
if (eq :single-escape (syntax-type c))
collect (read-char stream t nil t) into chars
else
collect c into chars
finally
(return (make-array (length chars)
:element-type 'character
:initial-contents chars))))
nil *standard-readtable*)
(make-dispatch-macro-character #\# t *standard-readtable*)
(mapc
#'(lambda (pair)
(set-dispatch-macro-character #\# (first pair) (second pair)
*standard-readtable*))
'((#\\ sharp-backslash) (#\' sharp-single-quote) (#\( sharp-left-parenthesis)
(#\* sharp-asterisk) (#\: sharp-colon) (#\. sharp-dot) (#\b sharp-b)
(#\o sharp-o) (#\x sharp-x) (#\r sharp-r) (#\c sharp-c) (#\a sharp-a)
(#\s sharp-s) (#\p sharp-p) (#\= sharp-equal) (#\# sharp-sharp)
(#\+ sharp-plus) (#\- sharp-minus) (#\| sharp-vertical-bar)))
(setq *readtable* (copy-readtable nil))