% -*- Mode: TeX -*-

\beginsubsection{Dynamic Control of the Lisp Reader}

Various aspects of the \term{Lisp reader} can be controlled dynamically.
\Seesection\Readtables\ and \secref\ReaderVars.

\endsubsection%{Dynamic Control of the Lisp Reader}
 
\beginsubsection{Effect of Readtable Case on the Lisp Reader}
\DefineSection{ReadtableCaseReadEffect}

The \term{readtable case} of the \term{current readtable} affects the \term{Lisp reader}
in the following ways:

\beginlist
\itemitem{\kwd{upcase}}

 When the \term{readtable case} is \kwd{upcase},
 unescaped constituent \term{characters} are converted to \term{uppercase},
 as specified in \secref\ReaderAlgorithm.

\itemitem{\kwd{downcase}}

 When the \term{readtable case} is \kwd{downcase},
 unescaped constituent \term{characters} are converted to \term{lowercase}.

\itemitem{\kwd{preserve}}

When the \term{readtable case} is \kwd{preserve},
 the case of all \term{characters} remains unchanged.

\itemitem{\kwd{invert}}

When the \term{readtable case} is \kwd{invert},
 then if all of the unescaped letters in the extended token are of the same \term{case}, 
 those (unescaped) letters are converted to the opposite \term{case}.

\endlist

\beginsubsubsection{Examples of Effect of Readtable Case on the Lisp Reader}
\DefineSection{ReadtableCaseReadExamples}

\code
 (defun test-readtable-case-reading ()
   (let ((*readtable* (copy-readtable nil)))
     (format t "READTABLE-CASE  Input   Symbol-name~
              ~%-----------------------------------~
              ~%")
     (dolist (readtable-case '(:upcase :downcase :preserve :invert))
       (setf (readtable-case *readtable*) readtable-case)
       (dolist (input '("ZEBRA" "Zebra" "zebra"))
         (format t "~&:~A~16T~A~24T~A"
                 (string-upcase readtable-case)
                 input
                 (symbol-name (read-from-string input)))))))
\endcode
 
The output from \f{(test-readtable-case-reading)} should be as follows:

\code
 READTABLE-CASE     Input Symbol-name
 -------------------------------------
    :UPCASE         ZEBRA   ZEBRA
    :UPCASE         Zebra   ZEBRA
    :UPCASE         zebra   ZEBRA
    :DOWNCASE       ZEBRA   zebra
    :DOWNCASE       Zebra   zebra
    :DOWNCASE       zebra   zebra
    :PRESERVE       ZEBRA   ZEBRA
    :PRESERVE       Zebra   Zebra
    :PRESERVE       zebra   zebra
    :INVERT         ZEBRA   zebra
    :INVERT         Zebra   Zebra
    :INVERT         zebra   ZEBRA
\endcode

\endsubsubsection%{Examples of Effect of Readtable Case on the Lisp Reader}

\endsubsection%{Effect of Readtable Case on the Lisp Reader}

\beginsubsection{Argument Conventions of Some Reader Functions}

\beginsubsubsection{The EOF-ERROR-P argument}

%% 22.2.1 2

\param{Eof-error-p} in input function calls
controls what happens if input is from a file (or any other
input source that has a definite end) and the end of the file is reached.
If \param{eof-error-p} is \term{true} (the default), 
an error \oftype{end-of-file} is signaled
at end of file.  If it is \term{false}, then no error is signaled, and instead
the function returns \param{eof-value}.

Functions such as \funref{read} that read the representation
of an \term{object} rather than a single
character always signals an error, regardless of \param{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, \funref{read} signals an error.  If a file ends in a 
\term{symbol} or a \term{number}
immediately followed by end-of-file, \funref{read} reads the 
\term{symbol} or
\term{number} 
successfully and when called again will
%%Barmar thought this wasn't needed:
% see the end-of-file and
% only then
act according to \param{eof-error-p}.
Similarly, \thefunction{read-line}
successfully reads the last line of a file even if that line
is terminated by end-of-file rather than the newline character.
Ignorable text, such as lines containing only \term{whitespace}\meaning{2} or comments,
are not considered to begin an \term{object}; 
if \funref{read} begins to read an \term{expression} but sees only such
ignorable text, it does not consider the file to end in the middle of an \term{object}.
Thus an \param{eof-error-p} argument controls what happens
when the file ends between \term{objects}.

\endsubsubsection%{The EOF-ERROR-P argument}

\beginsubsubsection{The RECURSIVE-P argument}

%% 22.2.1 4

If \param{recursive-p} is supplied and not \nil, it specifies that
this function call is not an outermost call to \funref{read} but an 
embedded call, typically from a \term{reader macro function}.
It is important to distinguish such recursive calls for three reasons.

%% 22.2.1 5
\beginlist
\itemitem{1.}
An outermost call establishes the context within which the
\f{\#\param{n}=} and \f{\#\param{n}\#} syntax is scoped.  Consider, for example,
the expression

\code
 (cons '#3=(p q r) '(x y . #3#))
\endcode
If the \term{single-quote} \term{reader macro} were defined in this way:

\code
 (set-macro-character #\\'       ;incorrect
    #'(lambda (stream char)
         (declare (ignore char))
         (list 'quote (read stream))))
\endcode

% then the expression could not be read properly, because there would be no way
% to know when \funref{read} is called recursively by the first
% occurrence of \f{'} that the label \f{\#3=} would be referred to
% later in the containing expression.
% There would be no way to know because \funref{read}
% could not determine that it was called by a \term{reader macro function}
% rather than from an outermost form.
%% per JonL:
then each call to the \term{single-quote} \term{reader macro function} would establish
independent contexts for the scope of \funref{read} information, including the scope of
identifications between markers like ``\f{\#3=}'' and ``\f{\#3\#}''.  However, for
this expression, the scope was clearly intended to be determined by the outer set 
of parentheses, so such a definition would be incorrect.
The correct way to define the \term{single-quote}
\term{reader macro} uses \param{recursive-p}: 

\code
 (set-macro-character #\\'       ;correct
    #'(lambda (stream char)
         (declare (ignore char))
         (list 'quote (read stream t nil t))))
\endcode

%% 22.2.1 6
\itemitem{2.}
A recursive call does not alter whether the reading process
is to preserve \term{whitespace}\meaning{2} or not (as determined by whether the
outermost call was to \funref{read} or \funref{read-preserving-whitespace}).
Suppose again that \term{single-quote} 
% had the first, incorrect, \term{reader macro}
% definition shown above.
%% per JonL:
were to be defined as shown above in the incorrect definition.
Then a call to \funref{read-preserving-whitespace}
that read the expression \f{'foo\SpaceChar} would fail to preserve the space
character following the symbol \f{foo} because the \term{single-quote}
\term{reader macro function} calls \funref{read}, 
not \funref{read-preserving-whitespace},
to read the following expression (in this case \f{foo}).
The correct definition, which passes the value \term{true} for \param{recursive-p}
to \funref{read}, allows the outermost call to determine
whether \term{whitespace}\meaning{2} is preserved.

%% 22.2.1 8
\itemitem{3.}
When end-of-file is encountered and the \param{eof-error-p} argument
is not \nil, the kind of error that is signaled may depend on the value
of \param{recursive-p}.  If \param{recursive-p} 
is \term{true}, then the end-of-file
is deemed to have occurred within the middle of a printed representation;
if \param{recursive-p} is \term{false}, then the end-of-file may be deemed to have
occurred between \term{objects} rather than within the middle of one.

\endlist

\endsubsubsection%{The EOF-ERROR-P argument}

\endsubsection%{Argument Conventions of Some Reader Functions}
