3 ;;; ParenScript is a simple language that looks a lot like Lisp, but
4 ;;; actually is JavaScript in disguise. Actually, it is JavaScript
5 ;;; embedded in a host Lisp. This way, JavaScript programs can be
6 ;;; seamlessly integrated in a Lisp web application. The programmer
7 ;;; doesn't have to resort to a different syntax, and JavaScript code
8 ;;; can easily be generated without having to resort to complicated
9 ;;; string generation or `FORMAT' expressions.
11 ;;; An example is worth more than a thousand words. The following Lisp
12 ;;; expression is a call to the ParenScript "compiler". The
13 ;;; ParenScript "compiler" transforms the expression in ParenScript
14 ;;; into an equivalent, human-readable expression in JavaScript.
20 ;;; The resulting javascript is:
22 function foobar
(a, b
) {
26 ;;; Great care has been given to the indentation and overall
27 ;;; readability of the generated JavaScript code.
31 ;;; ParenScript supports all the statements and expressions defined by
32 ;;; the EcmaScript 262 standard. Lisp symbols are converted to
33 ;;; camelcase, javascript-compliant syntax. This idea is taken from
34 ;;; Linj by Antonio Menezes Leitao. Here are a few examples of Lisp
35 ;;; symbol to JavaScript name conversion:
37 (js-to-string 'foobar
) => "foobar"
38 (js-to-string 'foo-bar
) => "fooBar"
39 (js-to-string 'foo-b-
@-r
) => "fooBAtR"
40 (js-to-string 'foo-b
@r
) => "fooBatr"
41 (js-to-string '*array
) => "Array"
42 (js-to-string '*math.floor
) => "Math.floor"
44 ;;; It also supports additional iteration constructs, relieving the
45 ;;; programmer of the burden of iterating over arrays.
46 ;;; `for' loops can be written using the customary `DO' syntax.
50 (j (aref arr i
) (aref arr i
)))
52 (alert (+ "i is " i
" and j is " j
))))
56 for
(var i
= 0, j
= arr
[i]; i < 10; i = ++i, j = arr[i]) {
57 alert
("i is " + i
+ " and j is " + j
);
60 ;;; ParenScript uses the Lisp reader, allowing for reader macros. It
61 ;;; also comes with its own macro environment, allowing host macros
62 ;;; and ParenScript to coexist without interfering with each other.
63 ;;; Furthermore, ParenScript uses its own compiler macro system,
64 ;;; allowing for an even further customization of the generation of
65 ;;; JavaScript. For example, the `1+' construct is implemented using a
66 ;;; ParenScript macro:
71 ;;; ParenScript allows the creation of JavaScript objects in a Lispy
72 ;;; way, using keyword arguments.
83 ;;; ParenScript features a HTML generator. Using the same syntax as
84 ;;; the `HTMLGEN' package of Franz, Inc., it can generate JavaScript
85 ;;; string expressions. This allows for a clean integration of HTML in
86 ;;; ParenScript code, instead of writing the tedious and error-prone
87 ;;; string generation code generally found in JavaScript.
90 (defun add-div (name href link-text
)
92 (html ((:div
:id name
)
94 ((:a
:href href
) link-text
))))))
98 function addDiv
(name, href
, linkText
) {
99 document.write
("<div id=\"" + name
+ "\">The link is: <a href=\""
101 + linkText
+ "</a></div>");
104 ;;; In order to have a complete web application framework available in
105 ;;; Lisp, ParenScript also provides a sexp-based syntax for CSS
106 ;;; files. Thus, a complete web application featuring HTML, CSS and
107 ;;; JavaScript documents can be generated using Lisp syntax, allowing
108 ;;; the programmer to use Lisp macros to factor out the redundancies
109 ;;; and complexities of Web syntax. For example, to generate a CSS
110 ;;; inline node in a HTML document:
112 (html-stream *standard-output
*
116 (css (* :border
"1px solid black")
117 (div.bl0rg
:font-family
"serif")
118 (("a:active" "a:hoover") :color
"black" :size
"200%"))))))
122 <html
><head
><style type
="text/css">
125 border
:1px solid black
;
142 ;;;# Getting ParenScript
144 ;;; ParenScript can be obtained from the BKNR subversion repository at
146 svn
://bknr.net
/trunk
/bknr
/src
/js
148 ;;; ParenScript does not depend on any part of BKNR though. You can
149 ;;; download snapshots of ParenScript at the webpage
151 http
://bknr.net
/parenscript
153 ;;; or using asdf-install.
155 (asdf-install:install
'parenscript
)
158 ;;; After downloading the ParenScript sourcecode, set up the ASDF
159 ;;; central registry by adding a symlink to "parenscript.asd". Then
160 ;;; use ASDF to load ParenScript. You may want to edit the ASDF file
161 ;;; to remove the dependency on the Allegroserve HTMLGEN facility.
163 (asdf:oos
'asdf
:load-op
:parenscript
)
165 ;;; ParenScript was written by Manuel Odendahl. He can be reached at