From: Jim Meehan
Subject: Re: conditional macro char?
Date: 
Message-ID: <1991Oct7.182220.9684@src.dec.com>
        Is is possible in Common LISP to tweak the reader such that
        a particular character is read as a macro character when it
        appears in certain contexts, but outside of these contexts the
        character retains its default syntax type (probably
        'constituent')?  For example, suppose I want the character #\!
        to be interpreted as a macro char iff it appears within a call
        to some macro I've defined...

There's lots you can do with the Lisp reader, but you cannot reverse
time.  Lisp calls READ, then EVAL, then PRINT.  Whatever you do at
READ-time, it's all over before you get to EVAL, and it's EVAL that
determines that a form is a call to a macro.  (More precisely, it's
during the syntax-analysis part of EVAL, but you get my point.)  In
other words, it's too late; macros cannot affect the reader.

Of course, a macro-expander can construct a string and call
READ-FROM-STRING, i.e., simulate its own READ-EVAL-PRINT loop, but
that's not applicable in your case (and besides, it's in very bad taste
:-).

What you CAN do is to introduce a new macro character, say $, whose
associated function changes the reader.  For example, the function
associated with $ could look like this:

    #'(LAMBDA (stream char)
        (DECLARE (IGNORE char))
        (LET ((*READTABLE* *my-readtable*))
          (READ stream T NIL T)))

In other words, it just calls READ, but in the "READ-time context"
of *my-readtable*, in which you can set things up any way you want,
including having !  do something unusual.  Of course, you'd have to
write your code so !  appeared inside an S-expression that was preceded
by $.

To give you a concrete example, consider how backquote, comma, and
at-sign work.  The special behavior of comma and comma/at-sign is
"defined" only inside a backquote expression; outside that context,
they behave differently (and usually signal errors).  CLtL says that
comma is a terminating macro character in the standard readtable, but
it didn't have to be that way.  Comma and at-sign could be perfectly
ordinary constituents in the standard readtable, and backquote could
change the readtable, just as in the example above, so that comma and
at-sign became macro characters.  Indeed, backquote shouldn't really
do anything with at-sign; it's comma that should "activate" at-sign,
but only when *it* has been activated by backquote!
From: Jay Nelson
Subject: Re: conditional macro char?
Date: 
Message-ID: <28F1F309.6B02@deneva.sdd.trw.com>
In article <····················@src.dec.com> ······@src.dec.com (Jim Meehan) writes:
>
>There's lots you can do with the Lisp reader, but you cannot reverse
>time.

Damn!  That's just what I need.  I guess I'll have to use a new language.


>What you CAN do is to introduce a new macro character, say $, whose
>associated function changes the reader.  For example, the function
>associated with $ could look like this:
>
>    #'(LAMBDA (stream char)
>        (DECLARE (IGNORE char))
>        (LET ((*READTABLE* *my-readtable*))
>          (READ stream T NIL T)))
>
>In other words, it just calls READ, but in the "READ-time context"
>of *my-readtable*, in which you can set things up any way you want,
>including having !  do something unusual.  Of course, you'd have to
>write your code so !  appeared inside an S-expression that was preceded
>by $.
>

I guess if the introduction of a dispatching macro character is too
messy (e.g., you are reading a bunch of stuff from a file that someone
else wrote) you could try:

(defmacro with-my-readtable (readtable &body body)
  (let ((old-table (gensym)))
    `(let ((,old-table *readtable*))
       (unwind-protect
         (progn (setf *readtable* readtable)
	        ,@body)
         (setf *readtable* ,old-table)))))
-- 
Jay Nelson  (TRW)  ···@wilbur.coyote.trw.com