Function read, read-preserving-whitespace

Syntax:

read &optional input-stream eof-error-p eof-value recursive-p object

read-preserving-whitespace &optional input-stream eof-error-p eof-value recursive-p object

Arguments and Values:

input-stream—an input stream designator.

eof-error-p—a generalized boolean. The default is true.

eof-value—an object. The default is nil.

recursive-p—a generalized boolean. The default is false.

object—an object (parsed by the Lisp reader) or the eof-value.

Description:

22.2.1 9read parses the printed representation of an object from input-stream and builds such an object.

22.2.1 14read-preserving-whitespace is like read but preserves any whitespace2 character that delimits the printed representation of the object. 22.2.1 17read-preserving-whitespace is exactly like read when the recursive-p argument to read-preserving-whitespace is true.

22.2.1 10 22.2.1 13When *read-suppress* is false, read throws away the delimiting character required by certain printed representations if it is a whitespace2 character; but read preserves the character (using unread-char) if it is syntactically meaningful, because it could be the start of the next expression. Already said in discussion of Double-Quote -kmp 25-Jan-92 2.5.2 3 \funref{read} always constructs a \term{simple string} when it reads the \term{double-quote} syntax. Moved to discussion of Double-Quote -kmp 25-Jan-92 \issue{CHARACTER-PROPOSAL:2-1-1} It is \term{implementation-dependent} which \term{attributes} are removed from characters within \term{double-quotes}. \endissue{CHARACTER-PROPOSAL:2-1-1} Already said in discussion of #* -kmp 25-Jan-92 2.5.3 2 \funref{read} always constructs a \term{simple bit vector} when it reads the \f{\#*} syntax.

If a file ends in a symbol or a number immediately followed by an end of file1, read reads the symbol or number successfully; when called again, it sees the end of file1 and only then acts according to eof-error-p. If a file contains ignorable text at the end, such as blank lines and comments, read does not consider it to end in the middle of an object. Moved to the discussion of tokenizing symbols. -kmp 25-Jan-92 \issue{CHARACTER-PROPOSAL:2-1-1} It is \term{implementation-dependent} which \term{attributes} are removed from \term{symbol} names. \endissue{CHARACTER-PROPOSAL:2-1-1}

If recursive-p is true, the call to read is expected to be made from within some function that itself has been called from read or from a similar input function, rather than from the top level.

22.2.1 9Both functions return the object read from input-stream. Eof-value is returned if eof-error-p is false and end of file is reached before the beginning of an object.

Examples:

!!! This example needs work.

 (read)
⊳ 'a
→ (QUOTE A)
 (with-input-from-string (is " ") (read is nil 'the-end)) → THE-END
 (defun skip-then-read-char (s c n)
    (if (char= c #\{) (read s t nil t) (read-preserving-whitespace s))
    (read-char-no-hang s)) → SKIP-THEN-READ-CHAR
 (let ((*readtable* (copy-readtable nil)))
    (set-dispatch-macro-character #\# #\{ #'skip-then-read-char)
    (set-dispatch-macro-character #\# #\} #'skip-then-read-char)
    (with-input-from-string (is "#{123 x #}123 y")
      (format t "~S ~S" (read is) (read is)))) → #\x, #\Space, NIL

22.2.1 15As an example, consider this reader macro definition:

JonL thinks this is easier to read if LOOP is used. (defun slash-reader (stream char) (declare (ignore char)) (do ((path (list (read-preserving-whitespace stream t nil t)) (cons (progn (read-char stream t nil t) (read-preserving-whitespace stream t nil t)) path))) ((not (eql (peek-char nil stream nil nil t) #\\/)) (cons 'path (nreverse path)))))

 (defun slash-reader (stream char)
   (declare (ignore char))
   `(path . ,(loop for dir = (read-preserving-whitespace stream t nil t)
                   then (progn (read-char stream t nil t)
                               (read-preserving-whitespace stream t nil t))
                   collect dir
                   while (eql (peek-char nil stream nil nil t) #\/))))
 (set-macro-character #\/ #'slash-reader)

22.2.1 16Consider now calling read on this expression:

 (zyedh /usr/games/zork /usr/games/boggle)
The / macro reads objects separated by more / characters; thus /usr/games/zork is intended to read as (path usr games zork). The entire example expression should therefore be read as

 (zyedh (path usr games zork) (path usr games boggle))
However, if read had been used instead of read-preserving-whitespace, then after the reading of the symbol zork, the following space would be discarded; the next call to peek-char would see the following /, and the loop would continue, producing this interpretation:

 (zyedh (path usr games zork usr games boggle))
There are times when whitespace2 should be discarded. If a command interpreter takes single-character commands, but occasionally reads an object then if the whitespace2 after a symbol is not discarded it might be interpreted as a command some time later after the symbol had been read.

Affected By:

*standard-input*, *terminal-io*, *readtable*, *read-default-float-format*, *read-base*, *read-suppress*, *package*, *read-eval*.

Exceptional Situations:

22.2.1 3read signals an error of type end-of-file, regardless of eof-error-p, if the file ends in the middle of an object representation. For example, if a file does not contain enough right parentheses to balance the left parentheses in it, read signals an error. This is detected when read or read-preserving-whitespace is called with recursive-p and eof-error-p non-nil, and end-of-file is reached before the beginning of an object.

If eof-error-p is true, an error of type end-of-file is signaled at the end of file.

See Also:

peek-char, read-char, unread-char, read-from-string, read-delimited-list, parse-integer, Chapter 2 (Syntax), Section 23.1 (Reader Concepts)

Notes:

None.