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
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