cl-quasi-quote

Common Lisp syntax extensions with quasi-quote

Introduction

Ever wanted to generate something where you have constant and dynamically generated parts interleaved? cl-quasi-quote provides a framework for such syntaxes and transformations, and also implements a few (e.g. XML and JavaScript) out of the box. But this small code fragment illustrates what the project is aiming at, and code speaks better than a million words anyway, so:

Example code, copy-pastable in (in-package :cl-quasi-quote-test)

;; Note: 「 and 」 are two unicode characters installed on a reader in the QQT package
;; that unconditionally reads its body into a string. It comes pretty handy in the
;; testsuite, which is full of string quoting, to avoid the headache of escaping...
(bind ((code-as-string 「<body
                          ,(string-upcase "some runtime generated <escaped> text")
                          `str("***<unescaped text 1>***")
                          ;; let's mix in some JavaScript here, with an unquoted part:
                          `js(print (+ 2 ,(+ 20 20))
                                `str("***<unescaped text 2>***"))>」))
  (pprint/xml+js code-as-string t)
  (emit/xml+js code-as-string))

Compiled (macroexpanded) code

;; the generated code (somewhat formatted and lowercased for readability)
(progn
  (write-string "<body>
" *xml+js-stream*)
  (write-quasi-quoted-string
   (bind ((*transformation* [XML->String]))
     (bind ((*xml-indent-level* (+ *xml-indent-level* 1)))
       (transform-quasi-quoted-xml-to-quasi-quoted-string/element
        (string-upcase "some runtime generated <escaped> text"))))
   *xml+js-stream*)
  (write-string "***<unescaped text 1>***
<script>
// <![CDATA[
print(2 + " *xml+js-stream*)
  (write-quasi-quoted-string
   (bind ((*transformation* [JS->String]))
     (bind ((*in-js-statement-context* nil)
            (*js-operator-precedence* 7)
            (*js-indent-level* (+ *js-indent-level* 0)))
       (transform-quasi-quoted-js-to-quasi-quoted-string (+ 20 20))))
   *xml+js-stream*)
  (write-string ", ***<unescaped text 2>***)
// ]]>
</script>
</body>
" *xml+js-stream*)
  +void+)

Output

;; the output of the generated code when run
"<body>
SOME RUNTIME GENERATED &lt;ESCAPED&gt; TEXT***<unescaped text 1>***
<script>
// <![CDATA[
print(2 + 40, ***<unescaped text 2>***)
// ]]>
</script>
</body>
"
Click there for more repl examples, or you can check out the unit tests in the darcs repo for even more gory details. This site is most probably lagging behind the code (as most handwritten documentations do).

A real-life example

For demonstrational (end experimentational) purposes we've created a CLOS class inspector using cl-quasi-quote and UCW.

Mailing Lists

Project members

Levente Mészáros
Attila Lendvai

(This project is part of the cl-dwim umbrella project)

Repo

You can browse the cl-quasi-quote darcs repository or get the tree with

darcs get --partial http://common-lisp.net/project/cl-quasi-quote/darcs/cl-quasi-quote

License

BSD / Public Domain