From: Paolo Amoroso
Subject: Pragmatic parsing macros
Date: 
Message-ID: <yxA=OxuhoYa1HZI1Sx0OSBEaA0Vh@4ax.com>
In section `B.1 META Parsing of Common Lisp Streams' of his well known
paper "Pragmatic Parsing in Common Lisp":

  http://linux.rice.edu/~rahul/hbaker/Prag-Parse.html
  http://linux.rice.edu/~rahul/hbaker/Prag-Parse.ps.Z

Henry Baker introduces the MATCH and MATCH-TYPE macros. MATCH is defined
like this:

  (defmacro match (x) `(when (eql (peek-char) ',x) (read-char)))

Why is MATCH a macro and not an ordinary function?

I have another question on the code included in the paper. Baker
extensively uses the &AUX lambda list keyword. What are the possible
reasons, stylistic or otherwise, for preferring &AUX in this context? The
paper was published in 1991, and since other options were available at the
time, I'm wondering about the reasons of Baker's design decision.


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/

From: Jochen Schmidt
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <9hnlcm$epd2f$1@ID-22205.news.dfncis.de>
Paolo Amoroso wrote:

> In section `B.1 META Parsing of Common Lisp Streams' of his well known
> paper "Pragmatic Parsing in Common Lisp":
> 
>   http://linux.rice.edu/~rahul/hbaker/Prag-Parse.html
>   http://linux.rice.edu/~rahul/hbaker/Prag-Parse.ps.Z
> 
> Henry Baker introduces the MATCH and MATCH-TYPE macros. MATCH is defined
> like this:
> 
>   (defmacro match (x) `(when (eql (peek-char) ',x) (read-char)))
> 
> Why is MATCH a macro and not an ordinary function?
> 
> I have another question on the code included in the paper. Baker
> extensively uses the &AUX lambda list keyword. What are the possible
> reasons, stylistic or otherwise, for preferring &AUX in this context? The
> paper was published in 1991, and since other options were available at the
> time, I'm wondering about the reasons of Baker's design decision.

I could imagine he used &aux because parsing with META needs always some
state variables and using an &aux in the lambda lists is a rather short 
form of doing this (instead of a full LET all the time)...
Particularily if you use LABELS for parsing with META this is a IMHO neat 
way to make the code a bit shorter.

I've uploaded my new CommonURI (ACL NET.URI clone) package on 

http://www.dataheaven.de

The new version uses the META parsing techinque instead of the former 
scan-macros for parsing the URIs. Included with this package is a file 
"meta.lisp" which implements the META Parsing technique for streams, 
strings and lists and wraps it all in some syntactic-sugar...
I've written this META module because I (re)use META so often that I start 
to see it as a design-flaw to COPY/PASTE it always again into the code...

ciao,
Jochen
From: Barry Margolin
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <wK207.30$NT6.1014@burlma1-snr2>
In article <····························@4ax.com>,
Paolo Amoroso  <·······@mclink.it> wrote:
>I have another question on the code included in the paper. Baker
>extensively uses the &AUX lambda list keyword. What are the possible
>reasons, stylistic or otherwise, for preferring &AUX in this context? The
>paper was published in 1991, and since other options were available at the
>time, I'm wondering about the reasons of Baker's design decision.

&AUX allows you to get local variables without introducint another level of
indentation due to LET.  It's a stylystic choice: some people like it,
others don't bother with it.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kent M Pitman
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <sfwn16nt42o.fsf@world.std.com>
Barry Margolin <······@genuity.net> writes:

> 
> In article <····························@4ax.com>,
> Paolo Amoroso  <·······@mclink.it> wrote:
> >I have another question on the code included in the paper. Baker
> >extensively uses the &AUX lambda list keyword. What are the possible
> >reasons, stylistic or otherwise, for preferring &AUX in this context? The
> >paper was published in 1991, and since other options were available at the
> >time, I'm wondering about the reasons of Baker's design decision.
> 
> &AUX allows you to get local variables without introducint another level of
> indentation due to LET.  It's a stylystic choice: some people like it,
> others don't bother with it.

Well, and to be honest, some of us think it's an abomination.

I used to use &AUX for a while a long time ago, but increasingly came to
feel it was the syntactically wrong place to put local variables.  It is
not part of the argument-passing protocol.  I think it arose there because
some people who did (or maybe still do) think of the &AUX things as sort
of pseudo-args -- kind of like optionals that you don't have the option of
passing...   but over time, I think a lot of people just started using it
to compute all kinds of junk that didn't seem proper to me, and finally I
just decided that function bodies are for definitions and function parameter
lists are for call-argument-handshaking.  So I don't use &AUX any more.

But that's just me.
From: Kaelin Colclasure
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <wu7kxgnx3g.fsf@soyuz.arslogica.com>
Kent M Pitman <······@world.std.com> writes:

> Well, and to be honest, some of us think it's an abomination.
> 
> I used to use &AUX for a while a long time ago, but increasingly came to
> feel it was the syntactically wrong place to put local variables.  It is
> not part of the argument-passing protocol.  I think it arose there because
> some people who did (or maybe still do) think of the &AUX things as sort
> of pseudo-args -- kind of like optionals that you don't have the option of
> passing...   but over time, I think a lot of people just started using it
> to compute all kinds of junk that didn't seem proper to me, and finally I
> just decided that function bodies are for definitions and function parameter
> lists are for call-argument-handshaking.  So I don't use &AUX any more.
> 
> But that's just me.

Hmmm, at one time I assumed &AUX was an anachronism that made it into
Common Lisp only because it was used in somebody's pet code base. But
then, when working on a system that did extensive Lisp code generation
(LSP), I had need to introduce lexical variables for certain generated
code snippets. It just happened that introducing them with &AUX was
vastly simpler than restructuring the generated code to introduce a
LET form in the appropriate place...

At that time, I was quite convinced that &AUX deserved preservation
for exactly that reason.

-- Kaelin
From: David Bakhash
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <m3hewkjcum.fsf@alum.mit.edu>
Hey,

it seemed that none of the followups answered the first part of your
question:

 paolo> Henry Baker introduces the MATCH and MATCH-TYPE macros. MATCH
 paolo> is defined like this:

 paolo>   (defmacro match (x) `(when (eql (peek-char) ',x) (read-char)))

 paolo> Why is MATCH a macro and not an ordinary function?

I think that the macro version is used here to make it behave in-line
(for speed), which is what this Meta parsing is all about.

In that case, though, I'd have guessed that #'match would use #'char=
instead of #'eql.

While the paper was certainly interesting, I had decided from reading
the paper that the only thing I'd ever use the Meta stuff for would be 
lists (wouldn't go near Meta for strings, and similarly for streams).

dave
From: Jochen Schmidt
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <9ih9rn$inanf$1@ID-22205.news.dfncis.de>
David Bakhash wrote:

> Hey,
> 
> it seemed that none of the followups answered the first part of your
> question:
> 
>  paolo> Henry Baker introduces the MATCH and MATCH-TYPE macros. MATCH
>  paolo> is defined like this:
> 
>  paolo>   (defmacro match (x) `(when (eql (peek-char) ',x) (read-char)))
> 
>  paolo> Why is MATCH a macro and not an ordinary function?
> 
> I think that the macro version is used here to make it behave in-line
> (for speed), which is what this Meta parsing is all about.
> 
> In that case, though, I'd have guessed that #'match would use #'char=
> instead of #'eql.
> 
> While the paper was certainly interesting, I had decided from reading
> the paper that the only thing I'd ever use the Meta stuff for would be
> lists (wouldn't go near Meta for strings, and similarly for streams).

I'm not sure why you came to that conclusion. The things you mentioned was 
implementation details in the paper that have nothing to do with the META 
parsing techinque per se.
I by myself found out experimentally that using TYPEP in e. g. CMUCL is 
incredible fast. I've compared CMUCL's TYPEP with generated code using CASE
and bit-vectors it is similar fast to CASE and a little bit faster than 
bit-vectors (or at least the way I used them).
So I don't think speed issues can be the drawback you see but what is it 
then?

ciao,
Jochen
From: Paolo Amoroso
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <EkFMO7OHK0B1z1ipD97UtbEsd0ba@4ax.com>
On Wed, 11 Jul 2001 08:42:29 GMT, David Bakhash <·····@alum.mit.edu> wrote:

> I think that the macro version is used here to make it behave in-line
> (for speed), which is what this Meta parsing is all about.

Isn't this use of macros generally frowned upon because it should be the
job of inline functions or compiler macros to do that?


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Jochen Schmidt
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <9ii2bu$ir36b$1@ID-22205.news.dfncis.de>
Paolo Amoroso wrote:

> On Wed, 11 Jul 2001 08:42:29 GMT, David Bakhash <·····@alum.mit.edu>
> wrote:
> 
>> I think that the macro version is used here to make it behave in-line
>> (for speed), which is what this Meta parsing is all about.
> 
> Isn't this use of macros generally frowned upon because it should be the
> job of inline functions or compiler macros to do that?

Yes but they (macros) are not really used because of this fact in META, but 
because they generate different code for different META-operator tokens.

For example:

(defmacro string-match (x &key source-symbol)
  (etypecase x)
    (character)
     `(when (and (< index end) (eql (char ,source-symbol index)  ,x))
        (incf index)))
    (string
     (let ((old-index-symbol (gensym "OLD-INDEX-")))
       `(let ((,old-index-symbol index))
          (or (and ,@(map 'list  
                                   #'(lambda (c) 
                                         `(string-match ,c                  
                                           :source-symbol ',source-symbol)) 
                                    x))
              (progn (setq index ,old-index-symbol) nil)))))))

generates different code depening on if the META-token is a character or a 
string.

You do not even have the META-token information available after the 
META-expression is compiled.

ciao,
Jochen
From: Paolo Amoroso
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <HOxNO1usR9FcQhlbGfWl3al7Bvp7@4ax.com>
On Wed, 11 Jul 2001 19:34:34 +0200, Jochen Schmidt <···@dataheaven.de>
wrote:

> Yes but they (macros) are not really used because of this fact in META, but 
> because they generate different code for different META-operator tokens.
[...]
> (defmacro string-match (x &key source-symbol)
>   (etypecase x)
[...]

What about MATCH?

  (defmacro match (x) `(when (eql (peek-char) ',x) (read-char)))

Shouldn't the generated code be the same in this case? Are there other
reasons, besides inline expansion as has been suggested, why it's
preferable for MATCH to be a macro rather than a function in this context?


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Jochen Schmidt
Subject: Re: Pragmatic parsing macros
Date: 
Message-ID: <9ikv47$jlai6$1@ID-22205.news.dfncis.de>
Paolo Amoroso wrote:

> On Wed, 11 Jul 2001 19:34:34 +0200, Jochen Schmidt <···@dataheaven.de>
> wrote:
> 
>> Yes but they (macros) are not really used because of this fact in META,
>> but because they generate different code for different META-operator
>> tokens.
> [...]
>> (defmacro string-match (x &key source-symbol)
>>   (etypecase x)
> [...]
> 
> What about MATCH?
> 
>   (defmacro match (x) `(when (eql (peek-char) ',x) (read-char)))
> 
> Shouldn't the generated code be the same in this case? Are there other
> reasons, besides inline expansion as has been suggested, why it's
> preferable for MATCH to be a macro rather than a function in this context?

Sorry I've used STRING-MATCH of my own implementation of META:
In my implementation there are three macros for MATCH, STRING-MATCH, 
STREAM-MATCH and LIST-MATCH - depending on what kind of "medium" you are 
parsing. Therefore what I said above upon the STRING-MATCH macro counts the 
same way for the original MATCH macro.
In the simple example for MATCH you showed there is always generated the 
same code, but since you could enhance it (like STRING-MATCH or LIST-MATCH)
it _would_ generate different code. Therefore it is only a kind of 
consistency in design to create the simple MATCH as a macro too - simply 
because the task of MATCH is to _generate_ code and that is what macros are 
for.

ciao,
Jochen