X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fread.lisp;h=3c352b33184e451b4470c6e81384ed69284914d4;hb=68cd2db6542fa3442d46b0331ecf8be8f86c09c2;hp=ca76ed6e5e1c6ef5fa500fa3598a6a14ef2df88a;hpb=2ff4cf0a60d5187b27bc07c6bcfdef88cc89f22b;p=jscl.git diff --git a/src/read.lisp b/src/read.lisp index ca76ed6..3c352b3 100644 --- a/src/read.lisp +++ b/src/read.lisp @@ -88,6 +88,13 @@ (skip-whitespaces stream) (setq ch (%peek-char stream))))) +(defun discard-char (stream expected) + (let ((ch (%read-char stream))) + (when (null ch) + (error "End of file when character ~S was expected." expected)) + (unless (char= ch expected) + (error "Character ~S was found but ~S was expected." ch expected)))) + (defun %read-list (stream) (skip-whitespaces-and-comments stream) (let ((ch (%peek-char stream))) @@ -95,23 +102,31 @@ ((null ch) (error "Unspected EOF")) ((char= ch #\)) - (%read-char stream) + (discard-char stream #\)) nil) (t - (let ((car (ls-read-1 stream))) + (let* ((eof (gensym)) + (next (ls-read stream nil eof))) (skip-whitespaces-and-comments stream) - (cons car - (if (char= (%peek-char stream) #\.) - (progn - (%read-char stream) - (if (terminalp (%peek-char stream)) - (ls-read-1 stream) ; Dotted pair notation - (cons (let ((string (concat "." (read-escaped-until stream #'terminalp)))) - (or (values (!parse-integer string nil)) - (read-float string) - (read-symbol string))) - (%read-list stream)))) - (%read-list stream)))))))) + (cond + ((eq next eof) + (discard-char stream #\))) + (t + (cons next + (if (char= (%peek-char stream) #\.) + (progn + (discard-char stream #\.) + (if (terminalp (%peek-char stream)) + (prog1 (ls-read stream) ; Dotted pair notation + (skip-whitespaces-and-comments stream) + (let ((ch (%peek-char stream))) + (if (or (null ch) (char= #\) ch)) + (discard-char stream #\)) + (error "Multiple objects following . in a list")))) + (let ((token (concat "." (read-escaped-until stream #'terminalp)))) + (cons (interpret-token token) + (%read-list stream))))) + (%read-list stream)))))))))) (defun read-string (stream) (let ((string "") @@ -126,14 +141,14 @@ (setq ch (%read-char stream))) string)) -(defun read-sharp (stream) +(defun read-sharp (stream &optional eof-error-p eof-value) (%read-char stream) (ecase (%read-char stream) (#\' - (list 'function (ls-read-1 stream))) + (list 'function (ls-read stream))) (#\( (list-to-vector (%read-list stream))) (#\: (make-symbol - (unescape + (unescape-token (string-upcase-noescaped (read-escaped-until stream #'terminalp))))) (#\\ @@ -146,30 +161,27 @@ ((string= cname "newline") #\newline) (t (char cname 0))))) (#\+ - (let ((feature (read-until stream #'terminalp))) - (cond - ((string= feature "common-lisp") - (ls-read-1 stream) ;ignore - (ls-read-1 stream)) - ((string= feature "jscl") - (ls-read-1 stream)) - (t - (error "Unknown reader form."))))))) + (let ((feature (let ((symbol (ls-read stream))) + (unless (symbolp symbol) + (error "Invalid feature ~S" symbol)) + (intern (string symbol) "KEYWORD")))) + (ecase feature + (:common-lisp + (ls-read stream) + (ls-read stream eof-error-p eof-value)) + (:jscl + (ls-read stream eof-error-p eof-value)) + (:nil + (ls-read stream) + (ls-read stream eof-error-p eof-value))))))) -(defun unescape (x) +(defun unescape-token (x) (let ((result "")) (dotimes (i (length x)) (unless (char= (char x i) #\\) (setq result (concat result (string (char x i)))))) result)) -(defun escape-all (x) - (let ((result "")) - (dotimes (i (length x)) - (setq result (concat result "\\")) - (setq result (concat result (string (char x i))))) - result)) - (defun string-upcase-noescaped (s) (let ((result "") (last-escape nil)) @@ -215,7 +227,7 @@ (setq name (subseq string index)))) ;; Canonalize symbol name and package (setq name (if (equal package "JS") - (setq name (unescape name)) + (setq name (unescape-token name)) (setq name (string-upcase-noescaped name)))) (setq package (find-package package)) (if (or internalp @@ -292,8 +304,7 @@ ;; Optional exponent part (when (< index size) ;; Exponent-marker - (unless (member (string-upcase (string (char string index))) - '("E" "S" "F" "D" "L")) + (unless (find (char-upcase (char string index)) "ESFDL") (return)) (incf index) (unless (< index size) (return)) @@ -313,7 +324,7 @@ (unless (= index size) (return)) ;; Everything went ok, we have a float ;; XXX: Use FLOAT when implemented. - (/ (* sign (expt 10.0 (* exponent-sign exponent)) number) divisor)))) + (/ (* sign (expt 10.0 (* exponent-sign exponent)) number) divisor 1.0)))) (defun !parse-integer (string junk-allow) (block nil @@ -359,45 +370,42 @@ (values num index) (error "Junk detected.")))) -(defvar *eof* (gensym)) -(defun ls-read-1 (stream) + +(defun interpret-token (string) + (or (read-integer string) + (read-float string) + (read-symbol string))) + +(defun ls-read (stream &optional (eof-error-p t) eof-value) (skip-whitespaces-and-comments stream) (let ((ch (%peek-char stream))) (cond ((or (null ch) (char= ch #\))) - *eof*) + (if eof-error-p + (error "End of file") + eof-value)) ((char= ch #\() (%read-char stream) (%read-list stream)) ((char= ch #\') (%read-char stream) - (list 'quote (ls-read-1 stream))) + (list 'quote (ls-read stream))) ((char= ch #\`) (%read-char stream) - (list 'backquote (ls-read-1 stream))) + (list 'backquote (ls-read stream))) ((char= ch #\") (%read-char stream) (read-string stream)) ((char= ch #\,) (%read-char stream) (if (eql (%peek-char stream) #\@) - (progn (%read-char stream) (list 'unquote-splicing (ls-read-1 stream))) - (list 'unquote (ls-read-1 stream)))) + (progn (%read-char stream) (list 'unquote-splicing (ls-read stream))) + (list 'unquote (ls-read stream)))) ((char= ch #\#) (read-sharp stream)) (t (let ((string (read-escaped-until stream #'terminalp))) - (or (read-integer string) - (read-float string) - (read-symbol string))))))) - -(defun ls-read (stream &optional (eof-error-p t) eof-value) - (let ((x (ls-read-1 stream))) - (if (eq x *eof*) - (if eof-error-p - (error "End of file") - eof-value) - x))) + (interpret-token string)))))) (defun ls-read-from-string (string &optional (eof-error-p t) eof-value) (ls-read (make-string-stream string) eof-error-p eof-value))