July 06, 2005
Made for DSLs

Martin Fowler says “Lisp is probably the strongest example of expressing DSLs directly in the language itself.”

The example problem posed in that article is to read and parse some sort of log of service call records:

#123456789012345678901234567890123456789012345678901234567890
SVCLFOWLER         10101MS0120050313.........................
SVCLHOHPE          10201DX0320050315........................
SVCLTWO           x10301MRP220050329..............................
USGE10301TWO          x50214..7050329...............................

Rainer Joswig came up with a nice little Lisp solution, which boils down to this:

(defmapping service-call "SVCL"
  (04 18 customer-name)
  (19 23 customer-id)
  (24 27 call-type-code)
  (28 35 date-of-call-string)))
 
(defmapping usage "USGE"
  (04 08 customer-id)
  (09 22 customer-name)
  (30 30 cycle)
  (31 36 read-date)))

Which I think looks perfectly natural to any Lisp programmer.

You can see exactly the same sort of process at work in the Practical Common Lisp chapter on parsing MP3 files:

(define-binary-class id3-tag ()
  ((identifier     (iso-8859-1-string :length 3))
   (major-version  u1)
   (revision       u1)
   (flags          u1)
   (size           id3-tag-size)
   (frames         (id3-frames :tag-size size))))

(define-tagged-binary-class id3-frame ()
  ((id (frame-id :length 3))
   (size u3))
  (:dispatch (find-frame-class id)))

(I finally sat down and read my hardcover copy of Practical Common Lisp; I was very impressed. The design and coding is elegant, the exposition was extremely lucid, and the practical chapters are engaging. Thumbs up.)

You can see that there are some benefits to writing your DSL in your host language as opposed to in XML.

[Oops. I just saw that Bill Clementson already posted about this very same thing.]

Posted by jjwiseman at July 06, 2005 12:07 PM
Comments

While Lisp macrology is nice for the obvious reason that Lisp eschews the distinction between surface syntax and abstract syntax, a language that retains the distinction but still has a programmable parser is also very nice. I'm referring, of course, to Objective Caml and its camlp4 parsing and pretty-printing system. On a small scale, you see campl4 used to do things like embed parsers and lexers directly in source code. On a somewhat larger scale, that of a full-blown, albeit modest, DSL, there's the example of Graydon Hoare's One-Day Compilers.

The example of Practical Common Lisp's binary-file parsing macros is indeed a very good one—so good that I intend to rewrite them as camlp4 syntax extensions for O'Caml for a project I'm working on.

Posted by: Paul Snively on July 6, 2005 12:51 PM

It may interest some people reading Planet Lisp to know (in case it hasn't already been posted) that APress/Bookpool are having a sale where you can get Practical Common Lisp (and other APress books) for half price.

-- Nate

Posted by: Nate on July 7, 2005 05:21 AM

Forth is also quite good at this sort of metaprogramming. I seem to be continually drawn to languages (such as forth and lisp) that are good at metaprogramming/dsl evolution. Curiously, they both have elegant fundamental language definitions that will fit on less than a sheet of paper.

Posted by: David Mercer on July 7, 2005 04:36 PM

What discussion about dsl and lisp would be complete w/o "A Universal Scripting Framework or Lambda: the ultimate 'little language'": http://www.cc.gatech.edu/fac/Olin.Shivers/ll.ps

Posted by: mds on July 10, 2005 11:42 PM
Post a comment
Name:


Email Address:


URL:




Unless you answer this question, your comment will be classified as spam and will not be posted.
(I'll give you a hint: the answer is “lisp”.)

Comments:


Remember info?