(defmacro get-cat-entry (char rt)
;; KLUDGE: Only give this side-effect-free args.
;; FIXME: should probably become inline function
- `(elt (character-attribute-table ,rt)
- (char-code ,char)))
+ `(if (typep ,char 'base-char)
+ (elt (character-attribute-array ,rt) (char-code ,char))
+ (gethash ,char (character-attribute-hash-table ,rt) +char-attr-constituent+)))
(defun set-cat-entry (char newvalue &optional (rt *readtable*))
- (setf (elt (character-attribute-table rt)
- (char-code char))
- newvalue))
+ (if (typep char 'base-char)
+ (setf (elt (character-attribute-array rt) (char-code char)) newvalue)
+ ;; FIXME: could REMHASH if we're setting to
+ ;; +CHAR-ATTR-CONSTITUENT+
+ (setf (gethash char (character-attribute-hash-table rt)) newvalue)))
;;; the value actually stored in the character macro table. As per
;;; ANSI #'GET-MACRO-CHARACTER and #'SET-MACRO-CHARACTER, this can
;;; be either a function or NIL.
(eval-when (:compile-toplevel :execute)
(sb!xc:defmacro get-raw-cmt-entry (char readtable)
- `(svref (character-macro-table ,readtable)
- (char-code ,char))))
+ `(if (typep ,char 'base-char)
+ (svref (character-macro-array ,readtable) (char-code ,char))
+ ;; Note: DEFAULT here is NIL, not #'UNDEFINED-MACRO-CHAR, so
+ ;; that everything above the base-char range is a non-macro
+ ;; constituent by default.
+ (gethash ,char (character-macro-hash-table ,readtable) nil))))
;;; the value represented by whatever is stored in the character macro
;;; table. As per ANSI #'GET-MACRO-CHARACTER and #'SET-MACRO-CHARACTER,
#'read-token)))
(defun set-cmt-entry (char new-value-designator &optional (rt *readtable*))
- (setf (svref (character-macro-table rt)
- (char-code char))
+ (if (typep char 'base-char)
+ (setf (svref (character-macro-array rt) (char-code char))
+ (and new-value-designator
+ (%coerce-callable-to-fun new-value-designator)))
+ (setf (gethash char (character-macro-hash-table rt))
(and new-value-designator
- (%coerce-callable-to-fun new-value-designator))))
+ (%coerce-callable-to-fun new-value-designator)))))
(defun undefined-macro-char (stream char)
(unless *read-suppress*
(test-attribute char +char-attr-whitespace+ rt))
(defmacro constituentp (char &optional (rt '*readtable*))
- `(>= (get-cat-entry ,char ,rt) +char-attr-constituent+))
+ `(test-attribute ,char +char-attr-constituent+ ,rt))
(defmacro terminating-macrop (char &optional (rt '*readtable*))
`(test-attribute ,char +char-attr-terminating-macro+ ,rt))
-(defmacro escapep (char &optional (rt '*readtable*))
- `(test-attribute ,char +char-attr-escape+ ,rt))
+(defmacro single-escape-p (char &optional (rt '*readtable*))
+ `(test-attribute ,char +char-attr-single-escape+ ,rt))
(defmacro multiple-escape-p (char &optional (rt '*readtable*))
`(test-attribute ,char +char-attr-multiple-escape+ ,rt))
;; depends on actual attribute numbering above.
`(<= (get-cat-entry ,char ,rt) +char-attr-terminating-macro+))
\f
-;;;; secondary attribute table
+;;;; constituent traits (see ANSI 2.1.4.2)
;;; There are a number of "secondary" attributes which are constant
;;; properties of characters (as long as they are constituents).
-(defvar *secondary-attribute-table*)
-(declaim (type attribute-table *secondary-attribute-table*))
+(defvar *constituent-trait-table*)
+(declaim (type attribute-table *constituent-trait-table*))
-(defun !set-secondary-attribute (char attribute)
- (setf (elt *secondary-attribute-table* (char-code char))
- attribute))
+(defun !set-constituent-trait (char trait)
+ (aver (typep char 'base-char))
+ (setf (elt *constituent-trait-table* (char-code char))
+ trait))
-(defun !cold-init-secondary-attribute-table ()
- (setq *secondary-attribute-table*
- (make-array char-code-limit :element-type '(unsigned-byte 8)
+(defun !cold-init-constituent-trait-table ()
+ (setq *constituent-trait-table*
+ (make-array base-char-code-limit :element-type '(unsigned-byte 8)
:initial-element +char-attr-constituent+))
- (!set-secondary-attribute #\: +char-attr-package-delimiter+)
- (!set-secondary-attribute #\| +char-attr-multiple-escape+) ; |) [for EMACS]
- (!set-secondary-attribute #\. +char-attr-constituent-dot+)
- (!set-secondary-attribute #\+ +char-attr-constituent-sign+)
- (!set-secondary-attribute #\- +char-attr-constituent-sign+)
- (!set-secondary-attribute #\/ +char-attr-constituent-slash+)
+ (!set-constituent-trait #\: +char-attr-package-delimiter+)
+ (!set-constituent-trait #\. +char-attr-constituent-dot+)
+ (!set-constituent-trait #\+ +char-attr-constituent-sign+)
+ (!set-constituent-trait #\- +char-attr-constituent-sign+)
+ (!set-constituent-trait #\/ +char-attr-constituent-slash+)
(do ((i (char-code #\0) (1+ i)))
((> i (char-code #\9)))
- (!set-secondary-attribute (code-char i) +char-attr-constituent-digit+))
- (!set-secondary-attribute #\E +char-attr-constituent-expt+)
- (!set-secondary-attribute #\F +char-attr-constituent-expt+)
- (!set-secondary-attribute #\D +char-attr-constituent-expt+)
- (!set-secondary-attribute #\S +char-attr-constituent-expt+)
- (!set-secondary-attribute #\L +char-attr-constituent-expt+)
- (!set-secondary-attribute #\e +char-attr-constituent-expt+)
- (!set-secondary-attribute #\f +char-attr-constituent-expt+)
- (!set-secondary-attribute #\d +char-attr-constituent-expt+)
- (!set-secondary-attribute #\s +char-attr-constituent-expt+)
- (!set-secondary-attribute #\l +char-attr-constituent-expt+))
-
-(defmacro get-secondary-attribute (char)
- `(elt *secondary-attribute-table*
- (char-code ,char)))
+ (!set-constituent-trait (code-char i) +char-attr-constituent-digit+))
+ (!set-constituent-trait #\E +char-attr-constituent-expt+)
+ (!set-constituent-trait #\F +char-attr-constituent-expt+)
+ (!set-constituent-trait #\D +char-attr-constituent-expt+)
+ (!set-constituent-trait #\S +char-attr-constituent-expt+)
+ (!set-constituent-trait #\L +char-attr-constituent-expt+)
+ (!set-constituent-trait #\e +char-attr-constituent-expt+)
+ (!set-constituent-trait #\f +char-attr-constituent-expt+)
+ (!set-constituent-trait #\d +char-attr-constituent-expt+)
+ (!set-constituent-trait #\s +char-attr-constituent-expt+)
+ (!set-constituent-trait #\l +char-attr-constituent-expt+)
+ (!set-constituent-trait #\Space +char-attr-invalid+)
+ (!set-constituent-trait #\Newline +char-attr-invalid+)
+ (dolist (c (list backspace-char-code tab-char-code form-feed-char-code
+ return-char-code rubout-char-code))
+ (!set-constituent-trait (code-char c) +char-attr-invalid+)))
+
+(defmacro get-constituent-trait (char)
+ `(if (typep ,char 'base-char)
+ (elt *constituent-trait-table* (char-code ,char))
+ +char-attr-constituent+))
\f
;;;; readtable operations
+(defun shallow-replace/eql-hash-table (to from)
+ (maphash (lambda (k v) (setf (gethash k to) v)) from))
+
(defun copy-readtable (&optional (from-readtable *readtable*)
to-readtable)
(let ((really-from-readtable (or from-readtable *standard-readtable*))
(really-to-readtable (or to-readtable (make-readtable))))
- (replace (character-attribute-table really-to-readtable)
- (character-attribute-table really-from-readtable))
- (replace (character-macro-table really-to-readtable)
- (character-macro-table really-from-readtable))
+ (replace (character-attribute-array really-to-readtable)
+ (character-attribute-array really-from-readtable))
+ (shallow-replace/eql-hash-table
+ (character-attribute-hash-table really-to-readtable)
+ (character-attribute-hash-table really-from-readtable))
+ (replace (character-macro-array really-to-readtable)
+ (character-macro-array really-from-readtable))
+ (shallow-replace/eql-hash-table
+ (character-macro-hash-table really-to-readtable)
+ (character-macro-hash-table really-from-readtable))
(setf (dispatch-tables really-to-readtable)
- (mapcar (lambda (pair) (cons (car pair)
- (copy-seq (cdr pair))))
+ (mapcar (lambda (pair)
+ (cons (car pair)
+ (let ((table (make-hash-table)))
+ (shallow-replace/eql-hash-table table (cdr pair))
+ table)))
(dispatch-tables really-from-readtable)))
(setf (readtable-case really-to-readtable)
(readtable-case really-from-readtable))
optional readtable (defaults to the current readtable). The
FROM-TABLE defaults to the standard Lisp readtable when NIL."
(let ((really-from-readtable (or from-readtable *standard-readtable*)))
- ;; Copy FROM-CHAR entries to TO-CHAR entries, but make sure that if
- ;; FROM-CHAR is a constituent you don't copy non-movable secondary
- ;; attributes (constituent types), and that said attributes magically
- ;; appear if you transform a non-constituent to a constituent.
- (let ((att (get-cat-entry from-char really-from-readtable)))
- (if (constituentp from-char really-from-readtable)
- (setq att (get-secondary-attribute to-char)))
+ (let ((att (get-cat-entry from-char really-from-readtable))
+ (mac (get-raw-cmt-entry from-char really-from-readtable))
+ (from-dpair (find from-char (dispatch-tables really-from-readtable)
+ :test #'char= :key #'car))
+ (to-dpair (find to-char (dispatch-tables to-readtable)
+ :test #'char= :key #'car)))
(set-cat-entry to-char att to-readtable)
- (set-cmt-entry to-char
- (get-raw-cmt-entry from-char really-from-readtable)
- to-readtable)))
+ (set-cmt-entry to-char mac to-readtable)
+ (when from-dpair
+ (cond
+ (to-dpair
+ (let ((table (cdr to-dpair)))
+ (clrhash table)
+ (shallow-replace/eql-hash-table table (cdr from-dpair))))
+ (t
+ (let ((pair (cons to-char (make-hash-table))))
+ (shallow-replace/eql-hash-table (cdr pair) (cdr from-dpair))
+ (setf (dispatch-tables to-readtable)
+ (push pair (dispatch-tables to-readtable)))))))))
t)
(defun set-macro-character (char function &optional
by the reader. The NON-TERMINATINGP flag can be used to make the macro
character non-terminating, i.e. embeddable in a symbol name."
(let ((designated-readtable (or readtable *standard-readtable*)))
- (set-cat-entry char
- (if non-terminatingp
- (get-secondary-attribute char)
- +char-attr-terminating-macro+)
+ (set-cat-entry char (if non-terminatingp
+ +char-attr-constituent+
+ +char-attr-terminating-macro+)
designated-readtable)
(set-cmt-entry char function designated-readtable)
t)) ; (ANSI-specified return value)
(let ((stream (in-synonym-of stream)))
(if (ansi-stream-p stream)
(prepare-for-fast-read-char stream
- (do ((attribute-table (character-attribute-table *readtable*))
+ (do ((attribute-array (character-attribute-array *readtable*))
+ (attribute-hash-table
+ (character-attribute-hash-table *readtable*))
(char (fast-read-char t) (fast-read-char t)))
- ((/= (the fixnum (aref attribute-table (char-code char)))
+ ((/= (the fixnum
+ (if (typep char 'base-char)
+ (aref attribute-array (char-code char))
+ (gethash char attribute-hash-table +char-attr-constituent+)))
+char-attr-whitespace+)
(done-with-fast-read-char)
char)))
;; CLOS stream
- (do ((attribute-table (character-attribute-table *readtable*))
+ (do ((attribute-array (character-attribute-array *readtable*))
+ (attribute-hash-table
+ (character-attribute-hash-table *readtable*))
(char (read-char stream nil :eof) (read-char stream nil :eof)))
((or (eq char :eof)
- (/= (the fixnum (aref attribute-table (char-code char)))
+ (/= (the fixnum
+ (if (typep char 'base-char)
+ (aref attribute-array (char-code char))
+ (gethash char attribute-hash-table +char-attr-constituent+)))
+char-attr-whitespace+))
(if (eq char :eof)
(error 'end-of-file :stream stream)
(let ((*readtable* *standard-readtable*))
(flet ((whitespaceify (char)
+ (set-cmt-entry char nil)
(set-cat-entry char +char-attr-whitespace+)))
(whitespaceify (code-char tab-char-code))
- (whitespaceify #\linefeed)
- (whitespaceify #\space)
+ (whitespaceify #\Newline)
+ (whitespaceify #\Space)
(whitespaceify (code-char form-feed-char-code))
(whitespaceify (code-char return-char-code)))
- (set-cat-entry #\\ +char-attr-escape+)
- (set-cmt-entry #\\ #'read-token)
+ (set-cat-entry #\\ +char-attr-single-escape+)
+ (set-cmt-entry #\\ nil)
+
+ (set-cat-entry #\| +char-attr-multiple-escape+)
+ (set-cmt-entry #\| nil)
;; Easy macro-character definitions are in this source file.
(set-macro-character #\" #'read-string)
;; all constituents
(do ((ichar 0 (1+ ichar))
(char))
- ((= ichar #O200))
+ ((= ichar base-char-code-limit))
(setq char (code-char ichar))
(when (constituentp char *standard-readtable*)
- (set-cat-entry char (get-secondary-attribute char))
- (set-cmt-entry char nil)))))
+ (set-cmt-entry char nil)))))
\f
;;;; implementation of the read buffer
"Read from STREAM and return the value read, preserving any whitespace
that followed the object."
(if recursivep
- ;; a loop for repeating when a macro returns nothing
- (loop
- (let ((char (read-char stream eof-error-p *eof-object*)))
- (cond ((eofp char) (return eof-value))
- ((whitespacep char))
- (t
- (let* ((macrofun (get-coerced-cmt-entry char *readtable*))
- (result (multiple-value-list
- (funcall macrofun stream char))))
- ;; Repeat if macro returned nothing.
- (if result (return (car result))))))))
- (let ((*sharp-equal-alist* nil))
+ ;; a loop for repeating when a macro returns nothing
+ (loop
+ (let ((char (read-char stream eof-error-p *eof-object*)))
+ (cond ((eofp char) (return eof-value))
+ ((whitespacep char))
+ (t
+ (let* ((macrofun (get-coerced-cmt-entry char *readtable*))
+ (result (multiple-value-list
+ (funcall macrofun stream char))))
+ ;; Repeat if macro returned nothing.
+ (when result
+ (return (unless *read-suppress* (car result)))))))))
+ (let ((*sharp-equal-alist* nil))
(read-preserving-whitespace stream eof-error-p eof-value t))))
;;; Return NIL or a list with one thing, depending.
eof-error-p
eof-value
recursivep)))
- ;; (This function generally discards trailing whitespace. If you
+ ;; This function generally discards trailing whitespace. If you
;; don't want to discard trailing whitespace, call
- ;; CL:READ-PRESERVING-WHITESPACE instead.)
+ ;; CL:READ-PRESERVING-WHITESPACE instead.
(unless (or (eql result eof-value) recursivep)
(let ((next-char (read-char stream nil nil)))
(unless (or (null next-char)
(do ((char (flush-whitespace input-stream)
(flush-whitespace input-stream))
(retlist ()))
- ((char= char endchar) (nreverse retlist))
+ ((char= char endchar) (unless *read-suppress* (nreverse retlist)))
(setq retlist (nconc (read-maybe-nothing input-stream char) retlist))))
\f
;;;; basic readmacro definitions
(defun read-comment (stream ignore)
(declare (ignore ignore))
- (let ((stream (in-synonym-of stream)))
- (if (ansi-stream-p stream)
- (prepare-for-fast-read-char stream
- (do ((char (fast-read-char nil nil)
- (fast-read-char nil nil)))
- ((or (not char) (char= char #\newline))
- (done-with-fast-read-char))))
- ;; CLOS stream
- (do ((char (read-char stream nil :eof) (read-char stream nil :eof)))
- ((or (eq char :eof) (char= char #\newline))))))
+ (handler-bind
+ ((character-decoding-error
+ #'(lambda (decoding-error)
+ (declare (ignorable decoding-error))
+ (style-warn "Character decoding error in a ;-comment at position ~A reading source file ~A, resyncing." (file-position stream) stream)
+ (invoke-restart 'attempt-resync))))
+ (let ((stream (in-synonym-of stream)))
+ (if (ansi-stream-p stream)
+ (prepare-for-fast-read-char stream
+ (do ((char (fast-read-char nil nil)
+ (fast-read-char nil nil)))
+ ((or (not char) (char= char #\newline))
+ (done-with-fast-read-char))))
+ ;; CLOS stream
+ (do ((char (read-char stream nil :eof) (read-char stream nil :eof)))
+ ((or (eq char :eof) (char= char #\newline)))))))
;; Don't return anything.
(values))
(do ((char (fast-read-char t) (fast-read-char t)))
((char= char closech)
(done-with-fast-read-char))
- (if (escapep char) (setq char (fast-read-char t)))
+ (if (single-escape-p char) (setq char (fast-read-char t)))
(ouch-read-buffer char)))
;; CLOS stream
(do ((char (read-char stream nil :eof) (read-char stream nil :eof)))
((or (eq char :eof) (char= char closech))
(if (eq char :eof)
(error 'end-of-file :stream stream)))
- (when (escapep char)
+ (when (single-escape-p char)
(setq char (read-char stream nil :eof))
(if (eq char :eof)
(error 'end-of-file :stream stream)))
t)
(t nil))
(values escapes colon))
- (cond ((escapep char)
+ (cond ((single-escape-p char)
;; It can't be a number, even if it's 1\23.
;; Read next char here, so it won't be casified.
(push *ouch-ptr* escapes)
((eofp ch)
(reader-eof-error stream "inside extended token"))
((multiple-escape-p ch) (return))
- ((escapep ch)
+ ((single-escape-p ch)
(let ((nextchar (read-char stream nil *eof-object*)))
(cond ((eofp nextchar)
(reader-eof-error stream "after escape character"))
(ouch-read-buffer ch))))))
(t
(when (and (constituentp char)
- (eql (get-secondary-attribute char)
- +char-attr-package-delimiter+)
+ (eql (get-constituent-trait char)
+ +char-attr-package-delimiter+)
(not colon))
(setq colon *ouch-ptr*))
(ouch-read-buffer char))))))
;;;; character classes
;;; Return the character class for CHAR.
-(defmacro char-class (char attable)
- `(let ((att (aref ,attable (char-code ,char))))
+;;;
+;;; FIXME: why aren't these ATT-getting forms using GET-CAT-ENTRY?
+;;; Because we've cached the readtable tables?
+(defmacro char-class (char attarray atthash)
+ `(let ((att (if (typep ,char 'base-char)
+ (aref ,attarray (char-code ,char))
+ (gethash ,char ,atthash +char-attr-constituent+))))
(declare (fixnum att))
- (if (<= att +char-attr-terminating-macro+)
- +char-attr-delimiter+
- att)))
+ (cond
+ ((<= att +char-attr-terminating-macro+) +char-attr-delimiter+)
+ ((< att +char-attr-constituent+) att)
+ (t (setf att (get-constituent-trait ,char))
+ (if (= att +char-attr-invalid+)
+ (%reader-error stream "invalid constituent")
+ att)))))
;;; Return the character class for CHAR, which might be part of a
;;; rational number.
-(defmacro char-class2 (char attable)
- `(let ((att (aref ,attable (char-code ,char))))
+(defmacro char-class2 (char attarray atthash)
+ `(let ((att (if (typep ,char 'base-char)
+ (aref ,attarray (char-code ,char))
+ (gethash ,char ,atthash +char-attr-constituent+))))
(declare (fixnum att))
- (if (<= att +char-attr-terminating-macro+)
- +char-attr-delimiter+
- (if (digit-char-p ,char *read-base*)
- +char-attr-constituent-digit+
- (if (= att +char-attr-constituent-digit+)
- +char-attr-constituent+
- att)))))
+ (cond
+ ((<= att +char-attr-terminating-macro+) +char-attr-delimiter+)
+ ((< att +char-attr-constituent+) att)
+ (t (setf att (get-constituent-trait ,char))
+ (cond
+ ((digit-char-p ,char *read-base*) +char-attr-constituent-digit+)
+ ((= att +char-attr-constituent-digit+) +char-attr-constituent+)
+ ((= att +char-attr-invalid+)
+ (%reader-error stream "invalid constituent"))
+ (t att))))))
;;; Return the character class for a char which might be part of a
;;; rational or floating number. (Assume that it is a digit if it
;;; could be.)
-(defmacro char-class3 (char attable)
- `(let ((att (aref ,attable (char-code ,char))))
+(defmacro char-class3 (char attarray atthash)
+ `(let ((att (if (typep ,char 'base-char)
+ (aref ,attarray (char-code ,char))
+ (gethash ,char ,atthash +char-attr-constituent+))))
(declare (fixnum att))
- (if possibly-rational
- (setq possibly-rational
- (or (digit-char-p ,char *read-base*)
- (= att +char-attr-constituent-slash+))))
- (if possibly-float
- (setq possibly-float
- (or (digit-char-p ,char 10)
- (= att +char-attr-constituent-dot+))))
- (if (<= att +char-attr-terminating-macro+)
- +char-attr-delimiter+
- (if (digit-char-p ,char (max *read-base* 10))
+ (cond
+ ((<= att +char-attr-terminating-macro+) +char-attr-delimiter+)
+ ((< att +char-attr-constituent+) att)
+ (t (setf att (get-constituent-trait ,char))
+ (when possibly-rational
+ (setq possibly-rational
+ (or (digit-char-p ,char *read-base*)
+ (= att +char-attr-constituent-slash+))))
+ (when possibly-float
+ (setq possibly-float
+ (or (digit-char-p ,char 10)
+ (= att +char-attr-constituent-dot+))))
+ (cond
+ ((digit-char-p ,char (max *read-base* 10))
(if (digit-char-p ,char *read-base*)
- +char-attr-constituent-digit+
- +char-attr-constituent+)
- att))))
+ (if (= att +char-attr-constituent-expt+)
+ +char-attr-constituent-digit-or-expt+
+ +char-attr-constituent-digit+)
+ +char-attr-constituent-decimal-digit+))
+ ((= att +char-attr-invalid+)
+ (%reader-error stream "invalid constituent"))
+ (t att))))))
\f
;;;; token fetching
(when *read-suppress*
(internal-read-extended-token stream firstchar nil)
(return-from read-token nil))
- (let ((attribute-table (character-attribute-table *readtable*))
+ (let ((attribute-array (character-attribute-array *readtable*))
+ (attribute-hash-table (character-attribute-hash-table *readtable*))
(package-designator nil)
(colons 0)
(possibly-rational t)
+ (seen-digit-or-expt nil)
(possibly-float t)
+ (was-possibly-float nil)
(escapes ())
(seen-multiple-escapes nil))
(reset-read-buffer)
(prog ((char firstchar))
- (case (char-class3 char attribute-table)
+ (case (char-class3 char attribute-array attribute-hash-table)
(#.+char-attr-constituent-sign+ (go SIGN))
(#.+char-attr-constituent-digit+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-digit-or-expt+
+ (setq seen-digit-or-expt t)
+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-decimal-digit+ (go LEFTDECIMALDIGIT))
(#.+char-attr-constituent-dot+ (go FRONTDOT))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
+ (#.+char-attr-invalid+ (%reader-error stream "invalid constituent"))
;; can't have eof, whitespace, or terminating macro as first char!
(t (go SYMBOL)))
SIGN ; saw "sign"
(unless char (go RETURN-SYMBOL))
(setq possibly-rational t
possibly-float t)
- (case (char-class3 char attribute-table)
+ (case (char-class3 char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-digit-or-expt+
+ (setq seen-digit-or-expt t)
+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-decimal-digit+ (go LEFTDECIMALDIGIT))
(#.+char-attr-constituent-dot+ (go SIGNDOT))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (return (make-integer)))
- (case (char-class3 char attribute-table)
+ (setq was-possibly-float possibly-float)
+ (case (char-class3 char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-decimal-digit+ (if possibly-float
+ (go LEFTDECIMALDIGIT)
+ (go SYMBOL)))
(#.+char-attr-constituent-dot+ (if possibly-float
(go MIDDLEDOT)
(go SYMBOL)))
- (#.+char-attr-constituent-expt+ (go EXPONENT))
+ (#.+char-attr-constituent-digit-or-expt+
+ (if (or seen-digit-or-expt (not was-possibly-float))
+ (progn (setq seen-digit-or-expt t) (go LEFTDIGIT))
+ (progn (setq seen-digit-or-expt t) (go LEFTDIGIT-OR-EXPT))))
+ (#.+char-attr-constituent-expt+
+ (if was-possibly-float
+ (go EXPONENT)
+ (go SYMBOL)))
+ (#.+char-attr-constituent-slash+ (if possibly-rational
+ (go RATIO)
+ (go SYMBOL)))
+ (#.+char-attr-delimiter+ (unread-char char stream)
+ (return (make-integer)))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
+ (#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
+ (#.+char-attr-package-delimiter+ (go COLON))
+ (t (go SYMBOL)))
+ LEFTDIGIT-OR-EXPT
+ (ouch-read-buffer char)
+ (setq char (read-char stream nil nil))
+ (unless char (return (make-integer)))
+ (case (char-class3 char attribute-array attribute-hash-table)
+ (#.+char-attr-constituent-digit+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-decimal-digit+ (bug "impossible!"))
+ (#.+char-attr-constituent-dot+ (go SYMBOL))
+ (#.+char-attr-constituent-digit-or-expt+ (go LEFTDIGIT))
+ (#.+char-attr-constituent-expt+ (go SYMBOL))
+ (#.+char-attr-constituent-sign+ (go EXPTSIGN))
(#.+char-attr-constituent-slash+ (if possibly-rational
(go RATIO)
(go SYMBOL)))
(#.+char-attr-delimiter+ (unread-char char stream)
(return (make-integer)))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
+ (#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
+ (#.+char-attr-package-delimiter+ (go COLON))
+ (t (go SYMBOL)))
+ LEFTDECIMALDIGIT ; saw "[sign] {decimal-digit}+"
+ (aver possibly-float)
+ (ouch-read-buffer char)
+ (setq char (read-char stream nil nil))
+ (unless char (go RETURN-SYMBOL))
+ (case (char-class char attribute-array attribute-hash-table)
+ (#.+char-attr-constituent-digit+ (go LEFTDECIMALDIGIT))
+ (#.+char-attr-constituent-dot+ (go MIDDLEDOT))
+ (#.+char-attr-constituent-expt+ (go EXPONENT))
+ (#.+char-attr-constituent-slash+ (aver (not possibly-rational))
+ (go SYMBOL))
+ (#.+char-attr-delimiter+ (unread-char char stream)
+ (go RETURN-SYMBOL))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(setq char (read-char stream nil nil))
(unless char (return (let ((*read-base* 10))
(make-integer))))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go RIGHTDIGIT))
(#.+char-attr-constituent-expt+ (go EXPONENT))
(#.+char-attr-delimiter+
(unread-char char stream)
(return (let ((*read-base* 10))
(make-integer))))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
- RIGHTDIGIT ; saw "[sign] {digit}* dot {digit}+"
+ RIGHTDIGIT ; saw "[sign] {decimal-digit}* dot {digit}+"
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (return (make-float stream)))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go RIGHTDIGIT))
(#.+char-attr-constituent-expt+ (go EXPONENT))
(#.+char-attr-delimiter+
(unread-char char stream)
(return (make-float stream)))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go RIGHTDIGIT))
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(t (go SYMBOL)))
FRONTDOT ; saw "dot"
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (%reader-error stream "dot context error"))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go RIGHTDIGIT))
(#.+char-attr-constituent-dot+ (go DOTS))
(#.+char-attr-delimiter+ (%reader-error stream "dot context error"))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
+ (setq possibly-float t)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-sign+ (go EXPTSIGN))
(#.+char-attr-constituent-digit+ (go EXPTDIGIT))
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go EXPTDIGIT))
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (return (make-float stream)))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go EXPTDIGIT))
(#.+char-attr-delimiter+
(unread-char char stream)
(return (make-float stream)))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class2 char attribute-table)
+ (case (char-class2 char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go RATIODIGIT))
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (return (make-ratio stream)))
- (case (char-class2 char attribute-table)
+ (case (char-class2 char attribute-array attribute-hash-table)
(#.+char-attr-constituent-digit+ (go RATIODIGIT))
(#.+char-attr-delimiter+
(unread-char char stream)
(return (make-ratio stream)))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (read-char stream nil nil))
(unless char (%reader-error stream "too many dots"))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-constituent-dot+ (go DOTS))
(#.+char-attr-delimiter+
(unread-char char stream)
(%reader-error stream "too many dots"))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(ouch-read-buffer char)
(setq char (fast-read-char nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
- (#.+char-attr-escape+ (done-with-fast-read-char)
- (go ESCAPE))
+ (case (char-class char attribute-array attribute-hash-table)
+ (#.+char-attr-single-escape+ (done-with-fast-read-char)
+ (go SINGLE-ESCAPE))
(#.+char-attr-delimiter+ (done-with-fast-read-char)
(unread-char char stream)
(go RETURN-SYMBOL))
(ouch-read-buffer char)
(setq char (read-char stream nil :eof))
(when (eq char :eof) (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
- (#.+char-attr-escape+ (go ESCAPE))
+ (case (char-class char attribute-array attribute-hash-table)
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-delimiter+ (unread-char char stream)
(go RETURN-SYMBOL))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL-LOOP))))))
- ESCAPE ; saw an escape
- ;; Don't put the escape in the read buffer.
+ SINGLE-ESCAPE ; saw a single-escape
+ ;; Don't put the escape character in the read buffer.
;; READ-NEXT CHAR, put in buffer (no case conversion).
(let ((nextchar (read-char stream nil nil)))
(unless nextchar
- (reader-eof-error stream "after escape character"))
+ (reader-eof-error stream "after single-escape character"))
(push *ouch-ptr* escapes)
(ouch-read-buffer nextchar))
(setq char (read-char stream nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(setq seen-multiple-escapes t)
(do ((char (read-char stream t) (read-char stream t)))
((multiple-escape-p char))
- (if (escapep char) (setq char (read-char stream t)))
+ (if (single-escape-p char) (setq char (read-char stream t)))
(push *ouch-ptr* escapes)
(ouch-read-buffer char))
(setq char (read-char stream nil nil))
(unless char (go RETURN-SYMBOL))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-delimiter+ (unread-char char stream) (go RETURN-SYMBOL))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go COLON))
(t (go SYMBOL)))
(setq escapes ())
(setq char (read-char stream nil nil))
(unless char (reader-eof-error stream "after reading a colon"))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-delimiter+
(unread-char char stream)
(%reader-error stream
"illegal terminating character after a colon: ~S"
char))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+ (go INTERN))
(t (go SYMBOL)))
(setq char (read-char stream nil nil))
(unless char
(reader-eof-error stream "after reading a colon"))
- (case (char-class char attribute-table)
+ (case (char-class char attribute-array attribute-hash-table)
(#.+char-attr-delimiter+
(unread-char char stream)
(%reader-error stream
"illegal terminating character after a colon: ~S"
char))
- (#.+char-attr-escape+ (go ESCAPE))
+ (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
(#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
(#.+char-attr-package-delimiter+
(%reader-error stream
(#\F 'single-float)
(#\D 'double-float)
(#\L 'long-float)))
- num)
- ;; Raymond Toy writes: We need to watch out if the
- ;; exponent is too small or too large. We add enough to
- ;; EXPONENT to make it within range and scale NUMBER
- ;; appropriately. This should avoid any unnecessary
- ;; underflow or overflow problems.
- (multiple-value-bind (min-expo max-expo)
- ;; FIXME: These forms are broken w.r.t.
- ;; cross-compilation portability, as the
- ;; cross-compiler will call the host's LOG function
- ;; while attempting to constant-fold. Maybe some sort
- ;; of load-time-form magic could be used instead?
- (case float-format
- ((short-float single-float)
- (values
- (log sb!xc:least-positive-normalized-single-float 10f0)
- (log sb!xc:most-positive-single-float 10f0)))
- ((double-float #!-long-float long-float)
- (values
- (log sb!xc:least-positive-normalized-double-float 10d0)
- (log sb!xc:most-positive-double-float 10d0)))
- #!+long-float
- (long-float
- (values
- (log sb!xc:least-positive-normalized-long-float 10l0)
- (log sb!xc:most-positive-long-float 10l0))))
- (let ((correction (cond ((<= exponent min-expo)
- (ceiling (- min-expo exponent)))
- ((>= exponent max-expo)
- (floor (- max-expo exponent)))
- (t
- 0))))
- (incf exponent correction)
- (setf number (/ number (expt 10 correction)))
- (setq num (make-float-aux number divisor float-format stream))
- (setq num (* num (expt 10 exponent)))
- (return-from make-float (if negative-fraction
- (- num)
- num))))))
- ;; should never happen
+ (result (make-float-aux (* (expt 10 exponent) number)
+ divisor float-format stream)))
+ (return-from make-float
+ (if negative-fraction (- result) result))))
(t (bug "bad fallthrough in floating point reader")))))
(defun make-float-aux (number divisor float-format stream)
;;;; cruft for dispatch macros
(defun make-char-dispatch-table ()
- (make-array char-code-limit :initial-element #'dispatch-char-error))
+ (make-hash-table))
(defun dispatch-char-error (stream sub-char ignore)
(declare (ignore ignore))
(dpair (find disp-char (dispatch-tables rt)
:test #'char= :key #'car)))
(if dpair
- (setf (elt (the simple-vector (cdr dpair))
- (char-code sub-char))
- (coerce function 'function))
+ (setf (gethash sub-char (cdr dpair)) (coerce function 'function))
(error "~S is not a dispatch char." disp-char))))
(defun get-dispatch-macro-character (disp-char sub-char
(dpair (find disp-char (dispatch-tables rt)
:test #'char= :key #'car)))
(if dpair
- (let ((dispatch-fun (elt (the simple-vector (cdr dpair))
- (char-code sub-char))))
- ;; Digits are also initialized in a dispatch table to
- ;; #'dispatch-char-error; READ-DISPATCH-CHAR handles them
- ;; separately. - CSR, 2002-04-12
- (if (eq dispatch-fun #'dispatch-char-error)
- nil
- dispatch-fun))
+ (values (gethash sub-char (cdr dpair)))
(error "~S is not a dispatch char." disp-char))))
(defun read-dispatch-char (stream char)
:test #'char= :key #'car)))
(if dpair
(funcall (the function
- (elt (the simple-vector (cdr dpair))
- (char-code sub-char)))
+ (gethash sub-char (cdr dpair) #'dispatch-char-error))
stream sub-char (if numargp numarg nil))
(%reader-error stream "no dispatch table for dispatch char")))))
\f
#!+sb-doc
"A resource of string streams for Read-From-String.")
-(defun read-from-string (string &optional eof-error-p eof-value
+(defun read-from-string (string &optional (eof-error-p t) eof-value
&key (start 0) end
preserve-whitespace)
#!+sb-doc
will take effect."
(declare (string string))
- (with-array-data ((string string)
+ (with-array-data ((string string :offset-var offset)
(start start)
(end (%check-vector-sequence-bounds string start end)))
(unless *read-from-string-spares*
- (push (internal-make-string-input-stream "" 0 0)
- *read-from-string-spares*))
+ (push (make-string-input-stream "" 0 0) *read-from-string-spares*))
(let ((stream (pop *read-from-string-spares*)))
- (setf (string-input-stream-string stream) string)
+ (setf (string-input-stream-string stream)
+ (coerce string '(simple-array character (*))))
(setf (string-input-stream-current stream) start)
(setf (string-input-stream-end stream) end)
(unwind-protect
(values (if preserve-whitespace
(read-preserving-whitespace stream eof-error-p eof-value)
(read stream eof-error-p eof-value))
- (string-input-stream-current stream))
+ (- (string-input-stream-current stream) offset))
(push stream *read-from-string-spares*)))))
\f
;;;; PARSE-INTEGER
(defun !reader-cold-init ()
(!cold-init-read-buffer)
- (!cold-init-secondary-attribute-table)
+ (!cold-init-constituent-trait-table)
(!cold-init-standard-readtable)
;; FIXME: This was commented out, but should probably be restored.
#+nil (!cold-init-integer-reader))