591 lines
28 KiB
HTML
591 lines
28 KiB
HTML
![]() |
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
|
||
|
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
|
||
|
<HEAD>
|
||
|
<TITLE>22.1.5. The Readtable</TITLE>
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<meta name="description" value=" The Readtable">
|
||
|
<meta name="keywords" value="clm">
|
||
|
<meta name="resource-type" value="document">
|
||
|
<meta name="distribution" value="global">
|
||
|
<P>
|
||
|
<b>Common Lisp the Language, 2nd Edition</b>
|
||
|
<BR> <HR><A NAME=tex2html3939 HREF="node193.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3937 HREF="node187.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3931 HREF="node191.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3941 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3942 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html3940 HREF="node193.html"> What the Print </A>
|
||
|
<B>Up:</B> <A NAME=tex2html3938 HREF="node187.html"> Printed Representation of </A>
|
||
|
<B> Previous:</B> <A NAME=tex2html3932 HREF="node191.html"> Standard Dispatching Macro </A>
|
||
|
<HR> <P>
|
||
|
<H2><A NAME=SECTION002615000000000000000>22.1.5. The Readtable</A></H2>
|
||
|
<P>
|
||
|
<A NAME=READTABLESECTION>Previous</A>
|
||
|
<A NAME=21728>sections</A>
|
||
|
describe the standard syntax accepted by the <tt>read</tt>
|
||
|
function. This section discusses the advanced topic of altering the
|
||
|
standard syntax either to provide extended syntax for Lisp objects
|
||
|
or to aid the writing of other parsers.
|
||
|
<P>
|
||
|
There is a data structure called the <i>readtable</i> that is used to
|
||
|
control the reader. It contains information about the syntax of each
|
||
|
character equivalent to that in table <A HREF="node188.html#StandardCharacterSyntaxTable">22-1</A>.
|
||
|
It is set up exactly as in
|
||
|
table <A HREF="node188.html#StandardCharacterSyntaxTable">22-1</A> to give the standard Common Lisp
|
||
|
meanings to all the characters, but the user can change the meanings of
|
||
|
characters to alter and customize the syntax of characters. It is also
|
||
|
possible to have several readtables describing different syntaxes and to
|
||
|
switch from one to another by binding the variable <tt>*readtable*</tt>.
|
||
|
<P>
|
||
|
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
|
||
|
Even if an implementation supports characters with non-zero bits and font attributes,
|
||
|
it need not (but may) allow for such characters to have syntax
|
||
|
descriptions in the readtable. However, every character of type
|
||
|
<tt>string-char</tt> must be represented in the readtable.
|
||
|
<br><img align=bottom alt="old_change_end" src="gif/old_change_end.gif">
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in March 1989 (CHARACTER-PROPOSAL) <A NAME=21738> </A>
|
||
|
to remove the type <tt>string-char</tt> and to replace the bits and font attributes
|
||
|
with the notion of implementation-defined attributes.
|
||
|
If any implementation-defined attributes are supported, an implementation
|
||
|
may (but need not) allow for such characters to have syntax
|
||
|
descriptions in the readtable. Characters that do not have non-standard values
|
||
|
for any implementation-defined attribute must be represented in the readtable.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Variable]</b><BR>
|
||
|
<tt>*readtable*</tt><P>The value of <tt>*readtable*</tt> is the current readtable. The initial
|
||
|
value of this is a readtable set up for standard Common Lisp syntax.
|
||
|
You can bind this variable to temporarily change the readtable being used.
|
||
|
<P>
|
||
|
To program the reader for a different syntax, a set of functions are
|
||
|
provided for manipulating readtables. Normally, you should begin
|
||
|
with a copy of the standard Common Lisp readtable and then customize
|
||
|
the individual characters within that copy.
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>copy-readtable &optional <i>from-readtable</i> <i>to-readtable</i></tt><P>A copy is made of <i>from-readtable</i>, which defaults to the current readtable
|
||
|
(the value of the global variable <tt>*readtable*</tt>). If <i>from-readtable</i>
|
||
|
is <tt>nil</tt>, then a copy of a standard Common Lisp readtable is made.
|
||
|
For example,
|
||
|
<P><pre>
|
||
|
(setq *readtable* (copy-readtable nil))
|
||
|
</pre><P>
|
||
|
will restore the input syntax to standard Common Lisp syntax, even if
|
||
|
the original readtable has been clobbered (assuming it is not so
|
||
|
badly clobbered that you cannot type in the above expression!).
|
||
|
On the other hand,
|
||
|
<P><pre>
|
||
|
(setq *readtable* (copy-readtable))
|
||
|
</pre><P>
|
||
|
will merely replace the current readtable with a copy of itself.
|
||
|
<P>
|
||
|
If <i>to-readtable</i> is unsupplied or <tt>nil</tt>, a fresh copy is made. Otherwise,
|
||
|
<i>to-readtable</i> must be a readtable, which is destructively copied into.
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>readtablep <i>object</i></tt><P><tt>readtablep</tt> is true if its argument is a readtable,
|
||
|
and otherwise is false.
|
||
|
<P><pre>
|
||
|
(readtablep x) == (typep x 'readtable)
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>set-syntax-from-char to-char <i>from-char</i> &optional <i>to-readtable</i> <i>from-readtable</i></tt><P>This makes the syntax of <i>to-char</i> in <i>to-readtable</i> be the same as the
|
||
|
syntax of <i>from-char</i> in <i>from-readtable</i>. The <i>to-readtable</i>
|
||
|
defaults to the current readtable (the value of the global variable
|
||
|
<tt>*readtable*</tt>), and <i>from-readtable</i> defaults to <tt>nil</tt>, meaning
|
||
|
to use the syntaxes from the standard Lisp readtable.
|
||
|
<p>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(ARGUMENTS-UNDERSPECIFIED) <A NAME=21772> </A>
|
||
|
to clarify that the <i>to-char</i> and <i>from-char</i>
|
||
|
must each be a character.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
Only attributes as shown in
|
||
|
table <A HREF="node188.html#StandardCharacterSyntaxTable">22-1</A> are copied; moreover,
|
||
|
if a <i>macro character</i> is copied, the macro definition function
|
||
|
is copied also.
|
||
|
However, attributes as shown
|
||
|
in table <A HREF="node189.html#StandardReadtableAttributesTable">22-3</A> are not copied;
|
||
|
they are ``hard-wired'' into the extended-token parser.
|
||
|
For example, if the definition of <tt>S</tt> is copied to <tt>*</tt>,
|
||
|
then <tt>*</tt> will become a <i>constituent</i> that is
|
||
|
<i>alphabetic</i> but cannot be used
|
||
|
as an exponent indicator for short-format floating-point number syntax.
|
||
|
<P>
|
||
|
It works to copy a macro definition from a character such as
|
||
|
<tt>"</tt> to another character; the standard definition for <tt>"</tt>
|
||
|
looks for another character that is the same as the character that
|
||
|
invoked it. It doesn't work to copy the definition of <tt>(</tt>
|
||
|
to <tt>{</tt>, for example; it can be done, but it lets one write lists
|
||
|
in the form <tt>{a b c)</tt>, not <tt>{a b c}</tt>,
|
||
|
because the definition
|
||
|
always looks for a closing parenthesis, not a closing brace. See the function
|
||
|
<tt>read-delimited-list</tt>, which is useful in this connection.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(RETURN-VALUES-UNSPECIFIED) <A NAME=21793> </A>
|
||
|
to specify that the <tt>set-syntax-from-char</tt> function returns <tt>t</tt>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
<tt>set-macro-character <i>char</i> <i>function</i> &optional
|
||
|
<i>non-terminating-p</i> <i>readtable</i>
|
||
|
</tt><tt>get-macro-character <i>char</i> &optional <i>readtable</i></tt>
|
||
|
</pre>
|
||
|
<tt>set-macro-character</tt> causes <i>char</i> to be a macro character that
|
||
|
when seen by <tt>read</tt> causes <i>function</i> to be called.
|
||
|
If <i>non-terminating-p</i> is not <tt>nil</tt> (it defaults to <tt>nil</tt>),
|
||
|
then it will be a non-terminating macro character: it may be embedded
|
||
|
within extended tokens.
|
||
|
<tt>set-macro-character</tt> returns <tt>t</tt>.
|
||
|
<P>
|
||
|
<tt>get-macro-character</tt> returns the function associated with <i>char</i>
|
||
|
and, as a second value, returns the <i>non-terminating-p</i> flag; it returns
|
||
|
<tt>nil</tt> if <i>char</i> does not have macro-character syntax. In each case,
|
||
|
<i>readtable</i> defaults to the current readtable.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(GET-MACRO-CHARACTER-READTABLE) <A NAME=21815> </A>
|
||
|
to specify that if <tt>nil</tt> is explicitly passed as the
|
||
|
second argument to <tt>get-macro-character</tt>, then the standard readtable is used.
|
||
|
This is consistent with the behavior of <tt>copy-readtable</tt>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
The <i>function</i> is called with two arguments, <i>stream</i>
|
||
|
and <i>char</i>. The <i>stream</i> is the input stream, and <i>char</i> is the
|
||
|
macro character itself.
|
||
|
In the simplest case, <i>function</i> may return a Lisp object.
|
||
|
This object is taken to be that whose printed representation
|
||
|
was the macro character and any following characters read
|
||
|
by the <i>function</i>.
|
||
|
As an example, a plausible definition of the standard single quote
|
||
|
character is:
|
||
|
<P><pre>
|
||
|
(defun single-quote-reader (stream char)
|
||
|
(declare (ignore char))
|
||
|
(list 'quote (read stream t nil t)))
|
||
|
|
||
|
(set-macro-character #\' #'single-quote-reader)
|
||
|
</pre><P>
|
||
|
(Note that <tt>t</tt> is specified for the <i>recursive-p</i> argument
|
||
|
to <tt>read</tt>; see section <A HREF="node195.html#CHARACTERINPUTSECTION">22.2.1</A>.)
|
||
|
The function reads an object following the single-quote and returns
|
||
|
a list of the symbol <tt>quote</tt> and that object.
|
||
|
The <i>char</i> argument is ignored.
|
||
|
<P>
|
||
|
|
||
|
<P>
|
||
|
The function may choose instead to return <i>zero</i> values
|
||
|
(for example, by using <tt>(values)</tt> as the return expression).
|
||
|
In this case, the macro character and whatever it may have read
|
||
|
contribute nothing to the object being read.
|
||
|
As an example, here is a plausible definition for the standard semicolon
|
||
|
(comment) character:
|
||
|
<P><pre>
|
||
|
(defun semicolon-reader (stream char)
|
||
|
(declare (ignore char))
|
||
|
;; First swallow the rest of the current input line.
|
||
|
;; End-of-file is acceptable for terminating the comment.
|
||
|
(do () ((char= (read-char stream nil #\Newline t) #\Newline)))
|
||
|
;; Return zero values.
|
||
|
(values))
|
||
|
|
||
|
(set-macro-character #\; #'semicolon-reader)
|
||
|
</pre><P>
|
||
|
(Note that <tt>t</tt> is specified for the <i>recursive-p</i> argument
|
||
|
to <tt>read-char</tt>; see section <A HREF="node195.html#CHARACTERINPUTSECTION">22.2.1</A>.)
|
||
|
<P>
|
||
|
The <i>function</i> should not have any side effects other than on the
|
||
|
<i>stream</i>.
|
||
|
Because of backtracking and restarting of the <tt>read</tt> operation,
|
||
|
front ends (such as editors and
|
||
|
rubout handlers) to the reader may cause
|
||
|
<i>function</i> to be called repeatedly during the
|
||
|
reading of a single expression in which the macro character only appears
|
||
|
once.
|
||
|
<P>
|
||
|
<hr>
|
||
|
<b>Compatibility note:</b> The ability to return either zero or one value
|
||
|
is the closest Common Lisp macro characters come to the splicing macro
|
||
|
characters of MacLisp or the <tt>splice</tt> macro characters of Interlisp.
|
||
|
The Common Lisp definition does not allow the splicing of arbitrarily many
|
||
|
values, but it does allow a macro-character function to decide
|
||
|
after it is invoked whether or not to yield a value, an option not
|
||
|
possible in MacLisp or Interlisp.
|
||
|
<P>
|
||
|
MacLisp has nothing equivalent to non-terminating macro characters.
|
||
|
The Interlisp equivalents of terminating and non-terminating macro
|
||
|
characters are macro characters with the <tt>ALWAYS</tt> or <tt>FIRST</tt> option,
|
||
|
respectively. Common Lisp has nothing equivalent to the Interlisp <tt>ALONE</tt>
|
||
|
macro-character option.
|
||
|
<hr>
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
Here is an example of a more elaborate set of read-macro characters
|
||
|
that I used in the implementation of the original
|
||
|
simulator for Connection Machine Lisp
|
||
|
[<A HREF="node368.html#CONNECTIONMACHINELISP">44</A>,<A HREF="node368.html#CMLISPIMPLEMENTATION">57</A>],
|
||
|
a parallel dialect of Common Lisp. This simulator was used to gain experience with
|
||
|
the language before freezing its design for full-scale implementation on a
|
||
|
Connection Machine computer system. This example illustrates the typical manner
|
||
|
in which a language designer can embed a new language within the syntactic and
|
||
|
semantic framework of Lisp, saving the effort of designing an implementation
|
||
|
from scratch.
|
||
|
<P>
|
||
|
Connection Machine Lisp introduces a new data type called a <i>xapping</i>,
|
||
|
which is simply an unordered set of ordered pairs of Lisp objects.
|
||
|
The first element of each pair is called the <i>index</i> and the second element
|
||
|
the <i>value</i>. We say that the xapping maps each index to its corresponding value.
|
||
|
No two pairs of the same xapping may have the same (that is, <tt>eql</tt>) index.
|
||
|
Xappings may be finite or infinite sets of pairs; only certain kinds
|
||
|
of infinite xappings are required, and special representations are used for them.
|
||
|
<P>
|
||
|
A finite xapping is notated by writing the pairs between braces, separated by whitespace.
|
||
|
A pair is notated by writing the index and the value, separated by a right arrow
|
||
|
(or an exclamation point if the host Common Lisp has no right-arrow character).
|
||
|
<P>
|
||
|
<hr>
|
||
|
<b>Remark:</b> The original language design used the right arrow; the exclamation point was
|
||
|
chosen to replace it on ASCII-only terminals because it is one of
|
||
|
the six characters <tt>[ ] { } ! ?</tt> reserved by Common Lisp to the user.
|
||
|
<P>
|
||
|
While preparing the TeX manuscript for this book I made a mistake
|
||
|
in font selection and discovered that by an absolutely incredible coincidence
|
||
|
the right arrow has the same numerical code (octal 41) within TeX fonts
|
||
|
as the ASCII exclamation point.
|
||
|
The result was that although the manuscript called for right arrows,
|
||
|
exclamation points came out in the printed copy. Imagine my astonishment!
|
||
|
<hr>
|
||
|
<P>
|
||
|
Here is an example of a xapping that maps three symbols to strings:
|
||
|
|
||
|
<P><pre>
|
||
|
{moe->"Oh, a wise guy, eh?" larry->"Hey, what's the idea?"
|
||
|
curly->"Nyuk, nyuk, nyuk!"}
|
||
|
</pre><P>
|
||
|
For convenience there are certain abbreviated notations.
|
||
|
If the index and value for a pair are the same object <i>x</i>,
|
||
|
then instead of having to write ``<i>x</i>-><i>x</i>''
|
||
|
(or, worse yet, ``<tt>#43=<i>x</i>->#43#</tt>'')
|
||
|
we may write simply <i>x</i> for the pair.
|
||
|
If all pairs of a xapping are of this form, we call the xapping a <i>xet</i>.
|
||
|
For example, the notation
|
||
|
<P><pre>
|
||
|
{baseball chess cricket curling bocce 43-man-squamish}
|
||
|
</pre><P>
|
||
|
is entirely equivalent in meaning to
|
||
|
<P><pre>
|
||
|
{baseball->baseball curling->curling cricket->cricket
|
||
|
chess->chess bocce->bocce 43-man-squamish->43-man-squamish}
|
||
|
</pre><P>
|
||
|
namely a xet of symbols naming six sports.
|
||
|
<P>
|
||
|
Another useful abbreviation covers the situation where the <i>n</i> pairs of a finite
|
||
|
xapping are integers, collectively covering a range from zero to <i>n</i>-1.
|
||
|
This kind of xapping is called a <i>xector</i> and may be notated by writing
|
||
|
the values between brackets in ascending order of their indices.
|
||
|
Thus
|
||
|
<P><pre>
|
||
|
[tinker evers chance]
|
||
|
</pre><P>
|
||
|
is merely an abbreviation for
|
||
|
<P><pre>
|
||
|
{tinker->0 evers->1 chance->2}
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
There are two kinds of infinite xapping: constant and universal.
|
||
|
A constant xapping <tt>{-><i>z</i>}</tt> maps every object to the same value <i>z</i>.
|
||
|
The universal xapping <tt>{->}</tt> maps every object to itself and is therefore the xet
|
||
|
of all Lisp objects, sometimes called simply the universe.
|
||
|
Both kinds of infinite xet may be modified by explicitly writing exceptions.
|
||
|
One kind of exception is simply a pair, which specifies the value for a particular index;
|
||
|
the other kind of exception is simply <i>k</i>->indicating that the xapping does
|
||
|
<i>not</i> have a pair with index <i>k</i> after all. Thus the notation
|
||
|
<P><pre>
|
||
|
{sky->blue grass->green idea->glass->->red}
|
||
|
</pre><P>
|
||
|
indicates a xapping that maps <tt>sky</tt> to <tt>blue</tt>, <tt>grass</tt> to <tt>green</tt>,
|
||
|
and every other object except <tt>idea</tt> and <tt>glass</tt> to <tt>red</tt>.
|
||
|
Note well that the presence or absence of whitespace on either side
|
||
|
of an arrow is crucial to the correct interpretation
|
||
|
of the notation.
|
||
|
<P>
|
||
|
Here is the representation of a xapping as a structure:
|
||
|
<P><pre>
|
||
|
(defstruct
|
||
|
(xapping (:print-function print-xapping)
|
||
|
(:constructor xap
|
||
|
(domain range &optional
|
||
|
(default ':unknown defaultp)
|
||
|
(infinite (and defaultp :constant))
|
||
|
(exceptions '()))))
|
||
|
domain
|
||
|
range
|
||
|
default
|
||
|
(infinite nil :type (member nil :constant :universal)
|
||
|
exceptions)
|
||
|
</pre><P>
|
||
|
The explicit pairs are represented as two parallel lists, one of indexes (<tt>domain</tt>)
|
||
|
and one of values (<tt>range</tt>). The <tt>default</tt> slot is the default value, relevant
|
||
|
only if the <tt>infinite</tt> slot is <tt>:constant</tt>.
|
||
|
The <tt>exceptions</tt> slot is a list of indices for which there are no values.
|
||
|
(See the end of section <A HREF="node200.html#FORMATSECTION">22.3.3</A> for the definition of <tt>print-xapping</tt>.)
|
||
|
<P>
|
||
|
Here, then, is the code for reading xectors in bracket notation:
|
||
|
<P><pre>
|
||
|
(defun open-bracket-macro-char (stream macro-char)
|
||
|
(declare (ignore macro-char))
|
||
|
(let ((range (read-delimited-list #\] stream t)))
|
||
|
(xap (iota-list (length range)) range)))
|
||
|
|
||
|
(set-macro-character #\[ #'open-bracket-macro-char)
|
||
|
(set-macro-character #\] (get-macro-character #\) ))
|
||
|
|
||
|
(defun iota-list (n) ;Return list of integers from <b>0</b> to <b><i>n</i>-1</b>
|
||
|
(do ((j (- n 1) (- j 1))
|
||
|
(z '() (cons j z)))
|
||
|
((< j 0) z)))
|
||
|
</pre><P>
|
||
|
The code for reading xappings in the more general brace notation, with all the
|
||
|
possibilities for xets (or individual xet pairs), infinite xappings, and exceptions,
|
||
|
is a bit more complicated; it is shown in table <A HREF="node192.html#XAPPINGMACROCHARTABLE">22-5</A>.
|
||
|
That code is used in conjunction with the initializations
|
||
|
<P><pre>
|
||
|
(set-macro-character #\{ #'open-brace-macro-char)
|
||
|
(set-macro-character #\} (get-macro-character #\) ))
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
<pre>
|
||
|
<A NAME=XAPPINGMACROCHARTABLE> </A>
|
||
|
----------------------------------------------------------------
|
||
|
Table 22-5: Macro Character Definition for Xapping Syntax
|
||
|
|
||
|
(defun open-brace-macro-char (s macro-char)
|
||
|
(declare (ignore macro-char))
|
||
|
(do ((ch (peek-char t s t nil t) (peek-char t s t nil t))
|
||
|
(domain '()) (range '()) (exceptions '()))
|
||
|
((char= ch #\})
|
||
|
(read-char s t nil t)
|
||
|
(construct-xapping (reverse domain) (reverse range)))
|
||
|
(cond ((char= ch #\->)
|
||
|
(read-char s t nil t)
|
||
|
(let ((nextch (peek-char nil s t nil t)))
|
||
|
(cond ((char= nextch #\})
|
||
|
(read-char s t nil t)
|
||
|
(return (xap (reverse domain)
|
||
|
(reverse range)
|
||
|
nil :universal exceptions)))
|
||
|
(t (let ((item (read s t nil t)))
|
||
|
(cond ((char= (peek-char t s t nil t) #\})
|
||
|
(read-char s t nil t)
|
||
|
(return (xap (reverse domain)
|
||
|
(reverse range)
|
||
|
item :constant
|
||
|
exceptions)))
|
||
|
(t (reader-error s
|
||
|
"Default -> item must be last"))))))))
|
||
|
(t (let ((item (read-preserving-whitespace s t nil t))
|
||
|
(nextch (peek-char nil s t nil t)))
|
||
|
(cond ((char= nextch #\->)
|
||
|
(read-char s t nil t)
|
||
|
(cond ((member (peek-char nil s t nil t)
|
||
|
'(#\Space #\Tab #\Newline))
|
||
|
(push item exceptions))
|
||
|
(t (push item domain)
|
||
|
(push (read s t nil t) range))))
|
||
|
((char= nch #\})
|
||
|
(read-char s t nil t)
|
||
|
(push item domain)
|
||
|
(push item range)
|
||
|
(return (xap (reverse domain) (reverse range))))
|
||
|
(t (push item domain)
|
||
|
(push item range))))))))
|
||
|
|
||
|
----------------------------------------------------------------
|
||
|
</pre>
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
<tt>make-dispatch-macro-character <i>char</i>
|
||
|
&optional <i>non-terminating-p</i> <i>readtable</i></tt>
|
||
|
</pre>This causes the character <i>char</i> to be a dispatching macro character
|
||
|
in <i>readtable</i> (which defaults to the current readtable).
|
||
|
If <i>non-terminating-p</i> is not <tt>nil</tt> (it defaults to <tt>nil</tt>),
|
||
|
then it will be a non-terminating macro character: it may be embedded
|
||
|
within extended tokens.
|
||
|
<tt>make-dispatch-macro-character</tt> returns <tt>t</tt>.
|
||
|
<P>
|
||
|
Initially every character in the dispatch table has a character-macro
|
||
|
function that signals an error. Use <tt>set-dispatch-macro-character</tt>
|
||
|
to define entries in the dispatch table.
|
||
|
<p>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(ARGUMENTS-UNDERSPECIFIED) <A NAME=21965> </A>
|
||
|
to clarify that <i>char</i> must be a character.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
<tt>set-dispatch-macro-character <i>disp-char</i> <i>sub-char</i> <i>function</i>
|
||
|
&optional <i>readtable</i>
|
||
|
</tt><tt>get-dispatch-macro-character <i>disp-char</i> <i>sub-char</i>
|
||
|
&optional <i>readtable</i></tt>
|
||
|
</pre>
|
||
|
<P><tt>set-dispatch-macro-character</tt>
|
||
|
causes <i>function</i> to be called when the <i>disp-char</i>
|
||
|
followed by <i>sub-char</i> is read. The <i>readtable</i> defaults to the
|
||
|
current readtable. The arguments and return values for <i>function</i> are
|
||
|
the same as for normal macro characters
|
||
|
except that <i>function</i> gets <i>sub-char</i>, not <i>disp-char</i>,
|
||
|
as its second argument and also receives a third
|
||
|
argument that is the non-negative integer whose decimal
|
||
|
representation appeared between
|
||
|
<i>disp-char</i> and <i>sub-char</i>, or <tt>nil</tt> if no decimal integer appeared
|
||
|
there.
|
||
|
<P>
|
||
|
The <i>sub-char</i> may not be one of the ten decimal digits;
|
||
|
they are always reserved for specifying an infix integer argument.
|
||
|
Moreover, if <i>sub-char</i> is a lowercase character
|
||
|
(see <tt>lower-case-p</tt>), its uppercase equivalent is used instead.
|
||
|
(This is how the rule is enforced that the case of a dispatch sub-character
|
||
|
doesn't matter.)
|
||
|
<P>
|
||
|
<tt>set-dispatch-macro-character</tt> returns <tt>t</tt>.
|
||
|
<P>
|
||
|
<tt>get-dispatch-macro-character</tt> returns the macro-character function
|
||
|
for <i>sub-char</i> under <i>disp-char</i>, or <tt>nil</tt> if there is no
|
||
|
function associated with <i>sub-char</i>.
|
||
|
<P>
|
||
|
If the <i>sub-char</i> is one of the ten decimal digits <tt>0 1 2 3 4 5 6 7 8 9</tt>,
|
||
|
<tt>get-dispatch-macro-character</tt> always returns <tt>nil</tt>.
|
||
|
If <i>sub-char</i> is a lowercase character,
|
||
|
its uppercase equivalent is used instead.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(GET-MACRO-CHARACTER-READTABLE) <A NAME=21998> </A>
|
||
|
to specify that if <tt>nil</tt> is explicitly passed as the
|
||
|
second argument to <tt>get-dispatch-macro-character</tt>, then the standard readtable is used.
|
||
|
This is consistent with the behavior of <tt>copy-readtable</tt>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
For either function,
|
||
|
an error is signaled if the specified <i>disp-char</i> is not in fact
|
||
|
a dispatch character in the specified readtable. It is necessary
|
||
|
to use <tt>make-dispatch-macro-character</tt> to set up the
|
||
|
dispatch character before specifying its sub-characters.
|
||
|
<P>
|
||
|
As an example, suppose one would like <tt>#$<i>foo</i></tt> to be read
|
||
|
as if it were <tt>(dollars <i>foo</i>)</tt>. One might say:
|
||
|
<P><pre>
|
||
|
(defun |#$-reader| (stream subchar arg)
|
||
|
(declare (ignore subchar arg))
|
||
|
(list 'dollars (read stream t nil t)))
|
||
|
|
||
|
(set-dispatch-macro-character #\# #\$ #'|#$-reader|)
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
<hr>
|
||
|
<b>Compatibility note:</b> This macro-character mechanism is different from
|
||
|
those in MacLisp, Interlisp, and Lisp Machine Lisp. Recently Lisp systems have
|
||
|
implemented very general readers, even readers so programmable that they
|
||
|
can parse arbitrary compiled BNF grammars. Unfortunately, these
|
||
|
readers can be complicated to use. This design is an attempt to make the
|
||
|
reader as simple as possible to understand, use, and implement.
|
||
|
Splicing macros have been eliminated; a recent informal poll indicates
|
||
|
that no one uses them to produce other than zero or one value. The
|
||
|
ability to access parts of the object preceding the macro character has
|
||
|
been eliminated. The MacLisp single-character-object feature has been
|
||
|
eliminated because it is seldom used and trivially obtainable by
|
||
|
defining a macro.
|
||
|
<P>
|
||
|
The user is encouraged to turn off most macro characters, turn
|
||
|
others into single-character-object macros, and then use <tt>read</tt>
|
||
|
purely as a lexical analyzer on top of which to build a parser.
|
||
|
It is unnecessary, however, to cater to more complex lexical analysis
|
||
|
or parsing than that needed for Common Lisp.
|
||
|
<hr>
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>readtable-case <i>readtable</i></tt><P>X3J13 voted in June 1989 (READ-CASE-SENSITIVITY) <A NAME=22018> </A>
|
||
|
to introduce the function <tt>readtable-case</tt> to
|
||
|
control the reader's interpretation of case.
|
||
|
It provides access to a slot in a readtable, and may be used with <tt>setf</tt>
|
||
|
to alter the state of that slot.
|
||
|
The possible values for the slot are <tt>:upcase</tt>, <tt>:downcase</tt>,
|
||
|
<tt>:preserve</tt>, and <tt>:invert</tt>; the <tt>readtable-case</tt> for the standard readtable
|
||
|
is <tt>:upcase</tt>.
|
||
|
Note that <tt>copy-readtable</tt> is required to copy the <tt>readtable-case</tt> slot
|
||
|
along with all other readtable information.
|
||
|
<P>
|
||
|
Once the reader has accumulated a token as described in section <A HREF="node188.html#READER">22.1.1</A>,
|
||
|
if the token is a symbol, ``replaceable'' characters (unescaped uppercase or
|
||
|
lowercase constituent characters)
|
||
|
may be modified under the control of the <tt>readtable-case</tt> of the current readtable:
|
||
|
<UL><LI> For <tt>:upcase</tt>, replaceable characters are converted to uppercase.
|
||
|
(This was the behavior specified by the first edition.)
|
||
|
<P>
|
||
|
<LI> For <tt>:downcase</tt>, replaceable characters are converted to lowercase.
|
||
|
<P>
|
||
|
<LI> For <tt>:preserve</tt>, the cases of all characters remain unchanged.
|
||
|
<P>
|
||
|
<LI> For <tt>:invert</tt>, if all of the replaceable letters
|
||
|
in the extended token are of the same case, they are all converted to the opposite case;
|
||
|
otherwise the cases of all characters in that token remain unchanged.
|
||
|
</UL>
|
||
|
As an illustration, consider the following code.
|
||
|
<P><pre>
|
||
|
(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)))))))
|
||
|
</pre><P>
|
||
|
The output from this test code should be
|
||
|
<P><pre>
|
||
|
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
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
The <tt>readtable-case</tt> of the current readtable also affects the printing
|
||
|
of symbols (see <tt>*print-case*</tt> and <tt>*print-escape*</tt>).
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR> <HR><A NAME=tex2html3939 HREF="node193.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3937 HREF="node187.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3931 HREF="node191.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3941 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3942 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html3940 HREF="node193.html"> What the Print </A>
|
||
|
<B>Up:</B> <A NAME=tex2html3938 HREF="node187.html"> Printed Representation of </A>
|
||
|
<B> Previous:</B> <A NAME=tex2html3932 HREF="node191.html"> Standard Dispatching Macro </A>
|
||
|
<HR> <P>
|
||
|
<HR>
|
||
|
<P><ADDRESS>
|
||
|
AI.Repository@cs.cmu.edu
|
||
|
</ADDRESS>
|
||
|
</BODY>
|