From: Dustin Withers
Subject: Implementing mandatory and optional productions in CL-YACC
Date: 
Message-ID: <1161748679.250870.69000@k70g2000cwa.googlegroups.com>
Hello All,

I'm using CL-YACC to parse EDI documents. I have a grammar that has
many productions that have optional terminators.  Currently I have a
very rudimentary macro around define-parser that creates many
productions and I would like something a little cleaner.  How would I
go about implementing away to tell my macro that these specific
terminators may come up anywhere from 1-n times?  Here is the nasty
define-parser macro if it helps anyone understand what I'm doing:

(defmacro define-edi-parser (name)
  `(define-parser ,name
    (:start-symbol 850document)
    (:terminals (ELEMENTS ISA GS ST BEG CSH DTM N1 PO1 CTT SE GE IEA))

    (850document
     (isaparent ieaseg #'list))
    (isaparent
     (isaseg gsparent seseg geseg #'list))

    ,(let ((x ()))
	  (dotimes (y 20)
	    (setf x (cons `(gsparent (gsseg stseg begseg cshseg dtmseg dtmseg
n1seg ,@(let ((po1segs ()))
											   (dotimes (z y)
											     (setf po1segs (append '(po1seg) po1segs)))
											   po1segs)
					    cttseg #'list)) x)))
	  x)
    (gsseg
     (GS ELEMENTS #'cons))
    (isaseg
     (ISA ELEMENTS #'cons))
    (ieaseg
     (IEA ELEMENTS #'list-cons))
    (seseg
     (SE ELEMENTS #'list-cons))
    (geseg
     (GE ELEMENTS #'list-cons))
    (stseg
     (ST ELEMENTS #'list-cons))
    (begseg
     (BEG ELEMENTS #'list-cons))
    (cshseg
     (CSH ELEMENTS #'list-cons))
    (dtmseg
     (DTM ELEMENTS #'list-cons))
    (n1seg
     (N1 ELEMENTS #'list-cons))
    (po1seg
     (PO1 ELEMENTS #'list-cons))
    (cttseg
     (CTT ELEMENTS #'list-cons))))

The 20 is hardcoded right now. There is probably some loop macro that
is better than dotimes but I know and understand dotimes so I used it,
sorry for the nastiness. There are many other fields (besides PO1SEGS)
that are optional.  With this setup it allows me to have anywhere from
0 to 19 PO1SEGS and not have parse-with-lexer puke when it finds some
unknown terminator (specifically a CTT, which comes after the PO1SEGs)

Thanks,
-dustin
From: Dustin Withers
Subject: Re: Implementing mandatory and optional productions in CL-YACC
Date: 
Message-ID: <1161839195.397222.266610@f16g2000cwb.googlegroups.com>
So how about a function that works like:

(build-production gsparent (gsseg stseg begseg cshseg dtmseg n1seg
po1seg cttseg #'list)
			      ((dtmseg 3) (po1seg 4)))

That will produce:

((gsparent (gsseg stseg begseg cshseg dtmseg n1seg po1seg cttseg
#'list))
 (gsparent (gsseg stseg begseg cshseg dtmseg dtmseg n1seg po1seg cttseg
#'list))
 (gsparent (gsseg stseg begseg cshseg dtmseg dtmseg dtmseg n1seg po1seg
cttseg #'list))
 (gsparent (gsseg stseg begseg cshseg dtmseg n1seg po1seg po1seg cttseg
#'list))
 (gsparent (gsseg stseg begseg cshseg dtmseg dtmseg n1seg po1seg po1seg
cttseg #'list))
 (gsparent (gsseg stseg begseg cshseg dtmseg dtmseg dtmseg n1seg po1seg
po1seg cttseg #'list))
 (etc....))

Does this make sense? The only thing that worries me is having
optionals that are very large creating HUGE productions but I think it
would work...Any ideas?  Maybe I should get under the hood of CL-YACC
and learn how I might make it do optionals?

-dustin