##// END OF EJS Templates
Bugfixes
naryl -
r51:cdf03d3e default
parent child Browse files
Show More
@@ -1,170 +1,170 b''
1
1
2 (in-package txt2web.lib)
2 (in-package txt2web.lib)
3
3
4 ;;;; Macros implementing some intrinsics where it makes sense
4 ;;;; Macros implementing some intrinsics where it makes sense
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6
6
7 ;;; 1loc
7 ;;; 1loc
8
8
9 ;;; 2var
9 ;;; 2var
10
10
11 (defpsmacro killvar (varname &optional index)
11 (defpsmacro killvar (varname &optional index)
12 `(api-call kill-var ,varname ,index))
12 `(api-call kill-var ,varname ,index))
13
13
14 (defpsmacro killall ()
14 (defpsmacro killall ()
15 `(api-call kill-all))
15 `(api-call kill-all))
16
16
17 ;;; 3expr
17 ;;; 3expr
18
18
19 (defpsmacro no (arg)
19 (defpsmacro no (arg)
20 `(- -1 ,arg))
20 `(- -1 ,arg))
21
21
22 ;;; 4code
22 ;;; 4code
23
23
24 (defpsmacro qspver ()
24 (defpsmacro qspver ()
25 "0.0.1")
25 "0.0.1")
26
26
27 (defpsmacro curloc ()
27 (defpsmacro curloc ()
28 `*current-location)
28 `*current-location)
29
29
30 (defpsmacro rnd ()
30 (defpsmacro rnd ()
31 `(funcall rand 1 1000))
31 `(funcall rand 1 1000))
32
32
33 (defpsmacro qspmax (&rest args)
33 (defpsmacro qspmax (&rest args)
34 (if (= 1 (length args))
34 (if (= 1 (length args))
35 `(*math.max.apply nil ,@args)
35 `(*math.max.apply nil ,@args)
36 `(*math.max ,@args)))
36 `(*math.max ,@args)))
37
37
38 (defpsmacro qspmin (&rest args)
38 (defpsmacro qspmin (&rest args)
39 (if (= 1 (length args))
39 (if (= 1 (length args))
40 `(*math.min.apply nil ,@args)
40 `(*math.min.apply nil ,@args)
41 `(*math.min ,@args)))
41 `(*math.min ,@args)))
42
42
43 ;;; 5arrays
43 ;;; 5arrays
44
44
45 (defpsmacro arrsize (name)
45 (defpsmacro arrsize (name)
46 `(api-call array-size ,name))
46 `(api-call array-size ,name))
47
47
48 ;;; 6str
48 ;;; 6str
49
49
50 (defpsmacro len (s)
50 (defpsmacro len (s)
51 `(length ,s))
51 `(length ,s))
52
52
53 (defpsmacro mid (s from &optional count)
53 (defpsmacro mid (s from &optional count)
54 `(chain ,s (substring ,from ,count)))
54 `(chain ,s (substring ,from ,count)))
55
55
56 (defpsmacro ucase (s)
56 (defpsmacro ucase (s)
57 `(chain ,s (to-upper-case)))
57 `(chain ,s (to-upper-case)))
58
58
59 (defpsmacro lcase (s)
59 (defpsmacro lcase (s)
60 `(chain ,s (to-lower-case)))
60 `(chain ,s (to-lower-case)))
61
61
62 (defpsmacro trim (s)
62 (defpsmacro trim (s)
63 `(chain ,s (trim)))
63 `(chain ,s (trim)))
64
64
65 (defpsmacro replace (s from to)
65 (defpsmacro qspreplace (s from to)
66 `(chain ,s (replace ,from ,to)))
66 `(chain ,s (replace ,from ,to)))
67
67
68 (defpsmacro val (s)
68 (defpsmacro val (s)
69 `(parse-int ,s 10))
69 `(parse-int ,s 10))
70
70
71 (defpsmacro qspstr (n)
71 (defpsmacro qspstr (n)
72 `(chain ,n (to-string)))
72 `(chain ,n (to-string)))
73
73
74 ;;; 7if
74 ;;; 7if
75
75
76 ;;; 8sub
76 ;;; 8sub
77
77
78 ;;; 9loops
78 ;;; 9loops
79
79
80 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
80 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
81
81
82 (defpsmacro exit ()
82 (defpsmacro exit ()
83 `(return-from nil (values)))
83 `(return-from nil (values)))
84
84
85 ;;; 10dynamic
85 ;;; 10dynamic
86
86
87 ;;; 11main
87 ;;; 11main
88
88
89 (defpsmacro desc (s)
89 (defpsmacro desc (s)
90 (declare (ignore s))
90 (declare (ignore s))
91 "")
91 "")
92
92
93 ;;; 12stat
93 ;;; 12stat
94
94
95 (defpsmacro showstat (enable)
95 (defpsmacro showstat (enable)
96 `(api-call enable-frame :stat ,enable))
96 `(api-call enable-frame :stat ,enable))
97
97
98 ;;; 13diag
98 ;;; 13diag
99
99
100 (defpsmacro msg (text)
100 (defpsmacro msg (text)
101 `(alert ,text))
101 `(alert ,text))
102
102
103 ;;; 14act
103 ;;; 14act
104
104
105 (defpsmacro showacts (enable)
105 (defpsmacro showacts (enable)
106 `(api-call enable-frame :acts ,enable))
106 `(api-call enable-frame :acts ,enable))
107
107
108 (defpsmacro delact (&optional name)
108 (defpsmacro delact (&optional name)
109 (if name
109 (if name
110 `(api-call del-act ,name)
110 `(api-call del-act ,name)
111 `(api-call del-act)))
111 `(api-call del-act)))
112
112
113 (defpsmacro cla ()
113 (defpsmacro cla ()
114 `(api-call clear-act))
114 `(api-call clear-act))
115
115
116 ;;; 15objs
116 ;;; 15objs
117
117
118 (defpsmacro showobjs (enable)
118 (defpsmacro showobjs (enable)
119 `(api-call enable-frame :objs ,enable))
119 `(api-call enable-frame :objs ,enable))
120
120
121 (defpsmacro countobj ()
121 (defpsmacro countobj ()
122 `(length *objs))
122 `(length *objs))
123
123
124 (defpsmacro getobj (index)
124 (defpsmacro getobj (index)
125 `(or (elt *objs ,index) ""))
125 `(or (elt *objs ,index) ""))
126
126
127 ;;; 16menu
127 ;;; 16menu
128
128
129 ;;; 17sound
129 ;;; 17sound
130
130
131 (defpsmacro isplay (filename)
131 (defpsmacro isplay (filename)
132 `(funcall (@ playing includes) ,filename))
132 `(funcall (@ playing includes) ,filename))
133
133
134 ;;; 18img
134 ;;; 18img
135
135
136 (defpsmacro view (&optional path)
136 (defpsmacro view (&optional path)
137 `(api-call show-image ,path))
137 `(api-call show-image ,path))
138
138
139 (defpsmacro img (&rest images)
139 (defpsmacro img (&rest images)
140 `(api-call show-inline-images :stat (list ,@images)))
140 `(api-call show-inline-images :stat (list ,@images)))
141
141
142 (defpsmacro *img (&rest images)
142 (defpsmacro *img (&rest images)
143 `(api-call show-inline-images :main (list ,@images)))
143 `(api-call show-inline-images :main (list ,@images)))
144
144
145 ;;; 19input
145 ;;; 19input
146
146
147 (defpsmacro showinput (enable)
147 (defpsmacro showinput (enable)
148 `(api-call enable-frame :input ,enable))
148 `(api-call enable-frame :input ,enable))
149
149
150 ;;; 20time
150 ;;; 20time
151
151
152 (defpsmacro wait (msec)
152 (defpsmacro wait (msec)
153 `(await (api-call sleep ,msec)))
153 `(await (api-call sleep ,msec)))
154
154
155 (defpsmacro settimer (interval)
155 (defpsmacro settimer (interval)
156 `(api-call set-timer ,interval))
156 `(api-call set-timer ,interval))
157
157
158 ;;; 21local
158 ;;; 21local
159
159
160 ;;; 22for
160 ;;; 22for
161
161
162 ;;; misc
162 ;;; misc
163
163
164 (defpsmacro opengame (&optional filename)
164 (defpsmacro opengame (&optional filename)
165 (declare (ignore filename))
165 (declare (ignore filename))
166 `(api-call opengame))
166 `(api-call opengame))
167
167
168 (defpsmacro savegame (&optional filename)
168 (defpsmacro savegame (&optional filename)
169 (declare (ignore filename))
169 (declare (ignore filename))
170 `(api-call savegame))
170 `(api-call savegame))
@@ -1,154 +1,153 b''
1
1
2 (in-package txt2web)
2 (in-package txt2web)
3
3
4 (defvar *app-name* "")
4 (defvar *app-name* "")
5
5
6 (defun entry-point-no-args ()
6 (defun entry-point-no-args ()
7 (format t "~A~%" uiop:*command-line-arguments*)
8 (entry-point uiop:*command-line-arguments*))
7 (entry-point uiop:*command-line-arguments*))
9
8
10 (defun entry-point (args)
9 (defun entry-point (args)
11 (setf *app-name* (uiop:argv0))
10 (setf *app-name* (uiop:argv0))
12 (let ((*package* (find-package :txt2web)))
11 (let ((*package* (find-package :txt2web)))
13 (catch :terminate
12 (catch :terminate
14 (let ((compiler (apply #'make-instance 'compiler (parse-opts args))))
13 (let ((compiler (apply #'make-instance 'compiler (parse-opts args))))
15 (write-compiled-file compiler))))
14 (write-compiled-file compiler))))
16 (values))
15 (values))
17
16
18 (defun parse-opts (args)
17 (defun parse-opts (args)
19 (let ((mode :sources)
18 (let ((mode :sources)
20 (data (list :sources nil :target nil :js nil :css nil :body nil :compile nil :beautify nil)))
19 (data (list :sources nil :target nil :js nil :css nil :body nil :compile nil :beautify nil)))
21 (loop :for arg :in args
20 (loop :for arg :in args
22 :do (alexandria:switch (arg :test #'string=)
21 :do (alexandria:switch (arg :test #'string=)
23 ("-o" (setf mode :target))
22 ("-o" (setf mode :target))
24 ("--js" (setf mode :js))
23 ("--js" (setf mode :js))
25 ("--css" (setf mode :css))
24 ("--css" (setf mode :css))
26 ("--body" (setf mode :body))
25 ("--body" (setf mode :body))
27 ("-c" (setf (getf data :compile) t))
26 ("-c" (setf (getf data :compile) t))
28 ("--beautify" (setf (getf data :beautify) t))
27 ("--beautify" (setf (getf data :beautify) t))
29 (t (push arg (getf data mode)))))
28 (t (push arg (getf data mode)))))
30 (unless (< 0 (length (getf data :sources)))
29 (unless (< 0 (length (getf data :sources)))
31 (report-error "There should be at least one source"))
30 (report-error "There should be at least one source"))
32 (unless (> 1 (length (getf data :target)))
31 (unless (> 1 (length (getf data :target)))
33 (report-error "There should be no more than one target"))
32 (report-error "There should be no more than one target"))
34 (unless (> 1 (length (getf data :body)))
33 (unless (> 1 (length (getf data :body)))
35 (report-error "There should be no more than one body"))
34 (report-error "There should be no more than one body"))
36 (unless (getf data :target)
35 (unless (getf data :target)
37 (setf (getf data :target)
36 (setf (getf data :target)
38 (let* ((sources (first (getf data :sources)))
37 (let* ((sources (first (getf data :sources)))
39 (tokens (uiop:split-string sources :separator "."))
38 (tokens (uiop:split-string sources :separator "."))
40 (target (format nil "~{~A~^.~}.html"
39 (target (format nil "~{~A~^.~}.html"
41 (butlast tokens))))
40 (butlast tokens))))
42 (list target))))
41 (list target))))
43 (list :sources (getf data :sources)
42 (list :sources (getf data :sources)
44 :target (first (getf data :target))
43 :target (first (getf data :target))
45 :js (getf data :js)
44 :js (getf data :js)
46 :css (getf data :css)
45 :css (getf data :css)
47 :body (first (getf data :body))
46 :body (first (getf data :body))
48 :compile (getf data :compile)
47 :compile (getf data :compile)
49 :beautify (getf data :beautify))))
48 :beautify (getf data :beautify))))
50
49
51 (defun print-usage ()
50 (defun print-usage ()
52 (lformat t :usage *app-name*))
51 (lformat t :usage *app-name*))
53
52
54 (defun parse-file (filename)
53 (defun parse-file (filename)
55 (p:parse 'txt2web-grammar
54 (p:parse 'txt2web-grammar
56 (alexandria:read-file-into-string filename)))
55 (alexandria:read-file-into-string filename)))
57
56
58 (defun report-error (fmt &rest args)
57 (defun report-error (fmt &rest args)
59 (format t "ERROR: ~A~%" (apply #'format nil fmt args))
58 (format t "ERROR: ~A~%" (apply #'format nil fmt args))
60 (print-usage)
59 (print-usage)
61 (throw :terminate nil))
60 (throw :terminate nil))
62
61
63 ;;; JS
62 ;;; JS
64
63
65 (defun minify-package (package-designator minify prefix)
64 (defun minify-package (package-designator minify prefix)
66 (setf (ps:ps-package-prefix package-designator) prefix)
65 (setf (ps:ps-package-prefix package-designator) prefix)
67 (if minify
66 (if minify
68 (ps:obfuscate-package package-designator)
67 (ps:obfuscate-package package-designator)
69 (ps:unobfuscate-package package-designator)))
68 (ps:unobfuscate-package package-designator)))
70
69
71 (defmethod js-sources ((compiler compiler))
70 (defmethod js-sources ((compiler compiler))
72 (let ((ps:*ps-print-pretty* (beautify compiler)))
71 (let ((ps:*ps-print-pretty* (beautify compiler)))
73 (cond ((beautify compiler)
72 (cond ((beautify compiler)
74 (minify-package "TXT2WEB.MAIN" nil "qsp_")
73 (minify-package "TXT2WEB.MAIN" nil "qsp_")
75 (minify-package "TXT2WEB.API" nil "qsp_api_")
74 (minify-package "TXT2WEB.API" nil "qsp_api_")
76 (minify-package "TXT2WEB.LIB" nil "qsp_lib_"))
75 (minify-package "TXT2WEB.LIB" nil "qsp_lib_"))
77 (t
76 (t
78 (minify-package "TXT2WEB.MAIN" t "_")
77 (minify-package "TXT2WEB.MAIN" t "_")
79 (minify-package "TXT2WEB.API" t "a_")
78 (minify-package "TXT2WEB.API" t "a_")
80 (minify-package "TXT2WEB.LIB" t "l_")))
79 (minify-package "TXT2WEB.LIB" t "l_")))
81 (format nil "~{~A~^~%~%~}" (mapcar #'ps:ps* (reverse (js compiler))))))
80 (format nil "~{~A~^~%~%~}" (mapcar #'ps:ps* (reverse (js compiler))))))
82
81
83 ;;; CSS
82 ;;; CSS
84
83
85 (defmethod css-sources ((compiler compiler))
84 (defmethod css-sources ((compiler compiler))
86 (format nil "~{~A~^~%~%~}" (css compiler)))
85 (format nil "~{~A~^~%~%~}" (css compiler)))
87
86
88 ;;; HTML
87 ;;; HTML
89
88
90 (defmethod html-sources ((compiler compiler))
89 (defmethod html-sources ((compiler compiler))
91 (let ((flute:*escape-html* nil)
90 (let ((flute:*escape-html* nil)
92 (body-template (body compiler))
91 (body-template (body compiler))
93 (js (js-sources compiler))
92 (js (js-sources compiler))
94 (css (css-sources compiler)))
93 (css (css-sources compiler)))
95 (with-output-to-string (out)
94 (with-output-to-string (out)
96 (write
95 (write
97 (flute:h
96 (flute:h
98 (html
97 (html
99 (head
98 (head
100 (title "SugarQSP"))
99 (title "SugarQSP"))
101 (body
100 (body
102 body-template
101 body-template
103 (style css)
102 (style css)
104 (script js))))
103 (script js))))
105 :stream out
104 :stream out
106 :pretty nil))))
105 :pretty nil))))
107
106
108 (defun filename-game (filename)
107 (defun filename-game (filename)
109 (let ((filename (alexandria:lastcar (uiop:split-string filename :separator "/"))))
108 (let ((filename (alexandria:lastcar (uiop:split-string filename :separator "/"))))
110 (format nil "~{~A~^.~}" (butlast (uiop:split-string filename :separator ".")))))
109 (format nil "~{~A~^.~}" (butlast (uiop:split-string filename :separator ".")))))
111
110
112 (defmethod initialize-instance ((compiler compiler) &key sources ((:js js-files)) ((:css css-files)) ((:body body-file)) compile &allow-other-keys)
111 (defmethod initialize-instance ((compiler compiler) &key sources ((:js js-files)) ((:css css-files)) ((:body body-file)) compile &allow-other-keys)
113 (call-next-method)
112 (call-next-method)
114 (with-slots (body css js)
113 (with-slots (body css js)
115 compiler
114 compiler
116 ;; Compile the game's JS
115 ;; Compile the game's JS
117 (dolist (source sources)
116 (dolist (source sources)
118 (let ((ps (parse-file source))
117 (let ((ps (parse-file source))
119 (game-name (filename-game source)))
118 (game-name (filename-game source)))
120 (destructuring-bind (kw &rest locations)
119 (destructuring-bind (kw &rest locations)
121 ps
120 ps
122 (unless (eq kw 'lib:game)
121 (unless (eq kw 'lib:game)
123 (report-error "Internal error!"))
122 (report-error "Internal error!"))
124 (push
123 (push
125 `(lib:game (,game-name) ,@locations)
124 `(lib:game (,game-name) ,@locations)
126 js))))
125 js))))
127 ;; Does the user need us to do anything else
126 ;; Does the user need us to do anything else
128 (unless compile
127 (unless compile
129 ;; Read in body
128 ;; Read in body
130 (when body-file
129 (when body-file
131 (setf body
130 (setf body
132 (alexandria:read-file-into-string body-file)))
131 (alexandria:read-file-into-string body-file)))
133 ;; Include js files
132 ;; Include js files
134 (dolist (js-file js-files)
133 (dolist (js-file js-files)
135 (push (format nil "////// Included file ~A~%~A" js-file
134 (push (format nil "////// Included file ~A~%~A" js-file
136 (alexandria:read-file-into-string js-file))
135 (alexandria:read-file-into-string js-file))
137 js))
136 js))
138 ;; Include css files
137 ;; Include css files
139 (when css-files
138 (when css-files
140 ;; User option overrides the default css
139 ;; User option overrides the default css
141 (setf css nil)
140 (setf css nil)
142 (dolist (css-file css-files)
141 (dolist (css-file css-files)
143 (push (format nil "////// Included file ~A~%~A" css-file
142 (push (format nil "////// Included file ~A~%~A" css-file
144 (alexandria:read-file-into-string css-file))
143 (alexandria:read-file-into-string css-file))
145 css))))))
144 css))))))
146
145
147 (defmethod write-compiled-file ((compiler compiler))
146 (defmethod write-compiled-file ((compiler compiler))
148 (alexandria:write-string-into-file
147 (alexandria:write-string-into-file
149 (if (compile-only compiler)
148 (if (compile-only compiler)
150 ;; Just the JS
149 ;; Just the JS
151 (js-sources compiler)
150 (js-sources compiler)
152 ;; All of it
151 ;; All of it
153 (html-sources compiler))
152 (html-sources compiler))
154 (target compiler) :if-exists :supersede))
153 (target compiler) :if-exists :supersede))
@@ -1,624 +1,624 b''
1
1
2 (in-package txt2web)
2 (in-package txt2web)
3
3
4 ;;;; Parses TXT source to an intermediate representation
4 ;;;; Parses TXT source to an intermediate representation
5
5
6 (eval-when (:compile-toplevel :load-toplevel :execute)
6 (eval-when (:compile-toplevel :load-toplevel :execute)
7 (defparameter *max-args* 10))
7 (defparameter *max-args* 10))
8
8
9 ;;; Utility
9 ;;; Utility
10
10
11 (defun remove-nth (list nth)
11 (defun remove-nth (list nth)
12 (append (subseq list 0 nth)
12 (append (subseq list 0 nth)
13 (subseq list (1+ nth))))
13 (subseq list (1+ nth))))
14
14
15 (defun not-quote (char)
15 (defun not-quote (char)
16 (not (eql #\' char)))
16 (not (eql #\' char)))
17
17
18 (defun not-doublequote (char)
18 (defun not-doublequote (char)
19 (not (eql #\" char)))
19 (not (eql #\" char)))
20
20
21 (defun not-brace (char)
21 (defun not-brace (char)
22 (not (eql #\} char)))
22 (not (eql #\} char)))
23
23
24 (defun not-integer (string)
24 (defun not-integer (string)
25 (when (find-if-not #'digit-char-p string)
25 (when (find-if-not #'digit-char-p string)
26 t))
26 t))
27
27
28 (defun not-newline (char)
28 (defun not-newline (char)
29 (not (eql #\newline char)))
29 (not (eql #\newline char)))
30
30
31 (defun id-any-char (char)
31 (defun id-any-char (char)
32 (and
32 (and
33 (not (digit-char-p char))
33 (not (digit-char-p char))
34 (not (eql #\newline char))
34 (not (eql #\newline char))
35 (not (find char " !:&=<>+-*/,'\"()[]{}"))))
35 (not (find char " !:&=<>+-*/,'\"()[]{}"))))
36
36
37 (defun intern-first (list)
37 (defun intern-first (list)
38 (list* (intern (string-upcase (first list)) "TXT2WEB.LIB")
38 (list* (intern (string-upcase (first list)) "TXT2WEB.LIB")
39 (rest list)))
39 (rest list)))
40
40
41 (eval-when (:compile-toplevel :load-toplevel :execute)
41 (eval-when (:compile-toplevel :load-toplevel :execute)
42 (defun remove-nil (list)
42 (defun remove-nil (list)
43 (remove nil list)))
43 (remove nil list)))
44
44
45 (defun binop-rest (list)
45 (defun binop-rest (list)
46 (destructuring-bind (ws1 operator ws2 operand2)
46 (destructuring-bind (ws1 operator ws2 operand2)
47 list
47 list
48 (declare (ignore ws1 ws2))
48 (declare (ignore ws1 ws2))
49 (list (intern (string-upcase operator) "TXT2WEB.LIB") operand2)))
49 (list (intern (string-upcase operator) "TXT2WEB.LIB") operand2)))
50
50
51 (defun do-binop% (left-op other-ops)
51 (defun do-binop% (left-op other-ops)
52 (if (null other-ops)
52 (if (null other-ops)
53 left-op
53 left-op
54 (destructuring-bind ((operator right-op) &rest rest-ops)
54 (destructuring-bind ((operator right-op) &rest rest-ops)
55 other-ops
55 other-ops
56 (if (and (listp left-op)
56 (if (and (listp left-op)
57 (eq (first left-op)
57 (eq (first left-op)
58 operator))
58 operator))
59 (do-binop% (append left-op (list right-op)) rest-ops)
59 (do-binop% (append left-op (list right-op)) rest-ops)
60 (do-binop% (list operator left-op right-op) rest-ops)))))
60 (do-binop% (list operator left-op right-op) rest-ops)))))
61
61
62 (defun do-binop (list)
62 (defun do-binop (list)
63 (destructuring-bind (left-op rest-ops)
63 (destructuring-bind (left-op rest-ops)
64 list
64 list
65 (do-binop% left-op
65 (do-binop% left-op
66 (mapcar #'binop-rest rest-ops))))
66 (mapcar #'binop-rest rest-ops))))
67
67
68 (p:defrule line-continuation (and #\_ #\newline)
68 (p:defrule line-continuation (and #\_ #\newline)
69 (:constant nil))
69 (:constant nil))
70
70
71 (p:defrule text-spaces (+ (or #\space #\tab line-continuation))
71 (p:defrule text-spaces (+ (or #\space #\tab line-continuation))
72 (:text t))
72 (:text t))
73
73
74 (p:defrule spaces (+ (or #\space #\tab line-continuation))
74 (p:defrule spaces (+ (or #\space #\tab line-continuation))
75 (:constant nil)
75 (:constant nil)
76 (:error-report nil))
76 (:error-report nil))
77
77
78 (p:defrule spaces? (* (or #\space #\tab line-continuation))
78 (p:defrule spaces? (* (or #\space #\tab line-continuation))
79 (:constant nil)
79 (:constant nil)
80 (:error-report nil))
80 (:error-report nil))
81
81
82 (p:defrule colon #\:
82 (p:defrule colon #\:
83 (:constant nil))
83 (:constant nil))
84
84
85 (p:defrule equal #\=
85 (p:defrule equal #\=
86 (:constant nil))
86 (:constant nil))
87
87
88 (p:defrule alphanumeric (alphanumericp character))
88 (p:defrule alphanumeric (alphanumericp character))
89
89
90 (p:defrule not-newline (not-newline character))
90 (p:defrule not-newline (not-newline character))
91
91
92 (p:defrule squote-esc "''"
92 (p:defrule squote-esc "''"
93 (:lambda (list)
93 (:lambda (list)
94 (p:text (elt list 0))))
94 (p:text (elt list 0))))
95
95
96 (p:defrule dquote-esc "\"\""
96 (p:defrule dquote-esc "\"\""
97 (:lambda (list)
97 (:lambda (list)
98 (p:text (elt list 0))))
98 (p:text (elt list 0))))
99
99
100 (p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:")))
100 (p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:")))
101 (or squote-esc (not-quote character))))
101 (or squote-esc (not-quote character))))
102 (:lambda (list)
102 (:lambda (list)
103 (p:text (mapcar #'second list))))
103 (p:text (mapcar #'second list))))
104
104
105 (p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:")))
105 (p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:")))
106 (or dquote-esc (not-doublequote character))))
106 (or dquote-esc (not-doublequote character))))
107 (:lambda (list)
107 (:lambda (list)
108 (p:text (mapcar #'second list))))
108 (p:text (mapcar #'second list))))
109
109
110 ;;; Identifiers
110 ;;; Identifiers
111
111
112 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curact curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit for freelib func getobj gosub goto gs gt if iif img *img inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc local maintxt max menu mid min mod msecscount msg nl *nl no nosave obj opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt step str strcomp strfind strpos to trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
112 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curact curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit for freelib func getobj gosub goto gs gt if iif img *img inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc local maintxt max menu mid min mod msecscount msg nl *nl no nosave obj opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt step str strcomp strfind strpos to trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
113
113
114 (defun trim-$ (str)
114 (defun trim-$ (str)
115 (if (char= #\$ (elt str 0))
115 (if (char= #\$ (elt str 0))
116 (subseq str 1)
116 (subseq str 1)
117 str))
117 str))
118
118
119 (defun qsp-keyword-p (id)
119 (defun qsp-keyword-p (id)
120 (member (intern (trim-$ (string-upcase id))) *keywords*))
120 (member (intern (trim-$ (string-upcase id))) *keywords*))
121
121
122 (defun not-qsp-keyword-p (id)
122 (defun not-qsp-keyword-p (id)
123 (not (member (intern (trim-$ (string-upcase id))) *keywords*)))
123 (not (member (intern (trim-$ (string-upcase id))) *keywords*)))
124
124
125 (p:defrule qsp-keyword (qsp-keyword-p identifier-raw))
125 (p:defrule qsp-keyword (qsp-keyword-p identifier-raw))
126
126
127 (p:defrule id-first (id-any-char character))
127 (p:defrule id-first (id-any-char character))
128 (p:defrule id-next (or (id-any-char character)
128 (p:defrule id-next (or (id-any-char character)
129 (digit-char-p character)))
129 (digit-char-p character)))
130 (p:defrule identifier-raw (and id-first (* id-next))
130 (p:defrule identifier-raw (and id-first (* id-next))
131 (:lambda (list)
131 (:lambda (list)
132 (intern (string-upcase (p:text list)) "TXT2WEB.LIB")))
132 (intern (string-upcase (p:text list)) "TXT2WEB.LIB")))
133
133
134 (p:defrule identifier (not-qsp-keyword-p identifier-raw))
134 (p:defrule identifier (not-qsp-keyword-p identifier-raw))
135
135
136 ;;; Strings
136 ;;; Strings
137
137
138 (p:defrule qsp-string (or normal-string brace-string))
138 (p:defrule qsp-string (or normal-string brace-string))
139
139
140 (p:defrule normal-string (or sstring dstring)
140 (p:defrule normal-string (or sstring dstring)
141 (:lambda (str)
141 (:lambda (str)
142 (list* 'lib:str (or str (list "")))))
142 (list* 'lib:str (or str (list "")))))
143
143
144 (p:defrule sstring (and #\' (* (or string-interpol
144 (p:defrule sstring (and #\' (* (or string-interpol
145 sstring-exec
145 sstring-exec
146 sstring-chars))
146 sstring-chars))
147 #\')
147 #\')
148 (:function second))
148 (:function second))
149
149
150 (p:defrule dstring (and #\" (* (or string-interpol
150 (p:defrule dstring (and #\" (* (or string-interpol
151 dstring-exec
151 dstring-exec
152 dstring-chars))
152 dstring-chars))
153 #\")
153 #\")
154 (:function second))
154 (:function second))
155
155
156 (p:defrule string-interpol (and "<<" expression ">>")
156 (p:defrule string-interpol (and "<<" expression ">>")
157 (:function second))
157 (:function second))
158
158
159 (p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character)))
159 (p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character)))
160 (:text t))
160 (:text t))
161
161
162 (p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character)))
162 (p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character)))
163 (:text t))
163 (:text t))
164
164
165 (p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\")
165 (p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\")
166 (:lambda (list)
166 (:lambda (list)
167 (list* 'lib:exec (p:parse 'exec-body (second list)))))
167 (list* 'lib:exec (p:parse 'exec-body (second list)))))
168
168
169 (p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\')
169 (p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\')
170 (:lambda (list)
170 (:lambda (list)
171 (list* 'lib:exec (p:parse 'exec-body (second list)))))
171 (list* 'lib:exec (p:parse 'exec-body (second list)))))
172
172
173 (p:defrule brace-string (and #\{ before-statement block-body #\})
173 (p:defrule brace-string (and #\{ before-statement block-body #\})
174 (:lambda (list)
174 (:lambda (list)
175 (list* 'lib:qspblock (third list))))
175 (list* 'lib:qspblock (third list))))
176
176
177 ;;; Location
177 ;;; Location
178
178
179 (p:defrule txt2web-grammar (and (* (or spaces #\newline))
179 (p:defrule txt2web-grammar (and (* (or spaces #\newline))
180 (* location))
180 (* location))
181 (:lambda (list)
181 (:lambda (list)
182 `(lib:game ,@(second list))))
182 `(lib:game ,@(second list))))
183
183
184 (p:defrule location (and location-header block-body location-end)
184 (p:defrule location (and location-header block-body location-end)
185 (:destructure (header body end)
185 (:destructure (header body end)
186 (declare (ignore end))
186 (declare (ignore end))
187 `(lib:location (,header) ,@body)))
187 `(lib:location (,header) ,@body)))
188
188
189 (p:defrule location-header (and #\#
189 (p:defrule location-header (and #\#
190 (+ not-newline)
190 (+ not-newline)
191 (and #\newline spaces? before-statement))
191 (and #\newline spaces? before-statement))
192 (:destructure (spaces1 name spaces2)
192 (:destructure (spaces1 name spaces2)
193 (declare (ignore spaces1 spaces2))
193 (declare (ignore spaces1 spaces2))
194 (string-upcase (string-trim " " (p:text name)))))
194 (string-upcase (string-trim " " (p:text name)))))
195
195
196 (p:defrule location-end (and #\- (* not-newline) #\newline before-statement)
196 (p:defrule location-end (and #\- (* not-newline) #\newline before-statement)
197 (:constant nil))
197 (:constant nil))
198
198
199 ;;; Block body
199 ;;; Block body
200
200
201 (p:defrule newline-block-body (and #\newline spaces? block-body)
201 (p:defrule newline-block-body (and #\newline spaces? block-body)
202 (:function third))
202 (:function third))
203
203
204 (p:defrule block-body (* statement)
204 (p:defrule block-body (* statement)
205 (:function remove-nil))
205 (:function remove-nil))
206
206
207 ;; Just for <a href="exec:...'>
207 ;; Just for <a href="exec:...'>
208 ;; Explicitly called from that rule's production
208 ;; Explicitly called from that rule's production
209 (p:defrule exec-body (and before-statement line-body)
209 (p:defrule exec-body (and before-statement line-body)
210 (:function second))
210 (:function second))
211
211
212 (p:defrule line-body (and inline-statement (* next-inline-statement))
212 (p:defrule line-body (and inline-statement (* next-inline-statement))
213 (:lambda (list)
213 (:lambda (list)
214 (list* (first list) (second list))))
214 (list* (first list) (second list))))
215
215
216 (p:defrule before-statement (* (or #\newline spaces))
216 (p:defrule before-statement (* (or #\newline spaces))
217 (:constant nil))
217 (:constant nil))
218
218
219 (p:defrule statement-end (or statement-end-real statement-end-block-close))
219 (p:defrule statement-end (or statement-end-real statement-end-block-close))
220
220
221 (p:defrule statement-end-real (and (or #\newline
221 (p:defrule statement-end-real (and (or #\newline
222 (and #\& spaces? (p:& statement%)))
222 (and #\& spaces? (p:& statement%)))
223 before-statement)
223 before-statement)
224 (:constant nil))
224 (:constant nil))
225
225
226 (p:defrule statement-end-block-close (or (p:& #\}))
226 (p:defrule statement-end-block-close (or (p:& #\}))
227 (:constant nil))
227 (:constant nil))
228
228
229 (p:defrule inline-statement (and statement% spaces?)
229 (p:defrule inline-statement (and statement% spaces?)
230 (:function first))
230 (:function first))
231
231
232 (p:defrule next-inline-statement (and #\& spaces? inline-statement)
232 (p:defrule next-inline-statement (and #\& spaces? inline-statement)
233 (:function third))
233 (:function third))
234
234
235 (p:defrule not-a-non-statement (and (p:! (p:~ "elseif"))
235 (p:defrule not-a-non-statement (and (p:! (p:~ "elseif"))
236 (p:! (p:~ "else"))
236 (p:! (p:~ "else"))
237 (p:! (p:~ "end"))))
237 (p:! (p:~ "end"))))
238
238
239 (p:defrule statement (and inline-statement statement-end)
239 (p:defrule statement (and inline-statement statement-end)
240 (:function first))
240 (:function first))
241
241
242 (p:defrule statement% (and not-a-non-statement
242 (p:defrule statement% (and not-a-non-statement
243 (or label comment string-output
243 (or label comment string-output
244 block non-returning-intrinsic local
244 block non-returning-intrinsic local
245 assignment expression-output))
245 assignment expression-output))
246 (:function second))
246 (:function second))
247
247
248 (p:defrule expr-stopper (or comment block non-returning-intrinsic))
248 (p:defrule expr-stopper (or comment block non-returning-intrinsic))
249
249
250 (p:defrule string-output qsp-string
250 (p:defrule string-output qsp-string
251 (:lambda (string)
251 (:lambda (string)
252 (list 'lib:main-pl string)))
252 (list 'lib:main-pl string)))
253
253
254 (p:defrule expression-output expression
254 (p:defrule expression-output expression
255 (:lambda (list)
255 (:lambda (list)
256 (list 'lib:main-pl list)))
256 (list 'lib:main-pl list)))
257
257
258 (p:defrule label (and colon identifier)
258 (p:defrule label (and colon identifier)
259 (:lambda (list)
259 (:lambda (list)
260 (intern (string (second list)) :keyword)))
260 (intern (string (second list)) :keyword)))
261
261
262 (p:defrule comment (and #\! (* (or qsp-string brace-comment text-spaces not-newline)))
262 (p:defrule comment (and #\! (* (or qsp-string brace-comment text-spaces not-newline)))
263 (:constant nil))
263 (:constant nil))
264
264
265 (p:defrule brace-comment (and #\{ (* (not-brace character)) #\})
265 (p:defrule brace-comment (and #\{ (* (not-brace character)) #\})
266 (:constant nil))
266 (:constant nil))
267
267
268 (p:defrule local (and (p:~ "local") spaces variable (p:? (and spaces? #\= spaces? expression)))
268 (p:defrule local (and (p:~ "local") spaces variable (p:? (and spaces? #\= spaces? expression)))
269 (:lambda (list)
269 (:lambda (list)
270 (list* 'lib:local (third list)
270 (list* 'lib:local (third list)
271 (when (fourth list)
271 (when (fourth list)
272 (list (fourth (fourth list)))))))
272 (list (fourth (fourth list)))))))
273
273
274 ;;; Blocks
274 ;;; Blocks
275
275
276 (p:defrule block (or block-act block-if block-for))
276 (p:defrule block (or block-act block-if block-for))
277
277
278 (p:defrule block-if (and block-if-head block-if-body)
278 (p:defrule block-if (and block-if-head block-if-body)
279 (:destructure (head body)
279 (:destructure (head body)
280 `(lib:qspcond (,@head ,@(first body))
280 `(lib:qspcond (,@head ,@(first body))
281 ,@(rest body))))
281 ,@(rest body))))
282
282
283 (p:defrule block-if-head (and (p:~ "if") spaces expression spaces? colon spaces?)
283 (p:defrule block-if-head (and (p:~ "if") spaces expression spaces? colon spaces?)
284 (:function remove-nil)
284 (:function remove-nil)
285 (:function cdr))
285 (:function cdr))
286
286
287 (p:defrule block-if-body (or block-if-ml block-if-sl)
287 (p:defrule block-if-body (or block-if-ml block-if-sl)
288 (:destructure (if-body elseifs else &rest ws)
288 (:destructure (if-body elseifs else &rest ws)
289 (declare (ignore ws))
289 (declare (ignore ws))
290 `(,(remove-nil if-body) ,@elseifs ,@(when else `((else ,@else))))))
290 `(,(remove-nil if-body) ,@elseifs ,@(when else `((else ,@else))))))
291
291
292 (p:defrule block-if-sl (and line-body
292 (p:defrule block-if-sl (and line-body
293 (p:? block-if-elseif-inline)
293 (p:? block-if-elseif-inline)
294 (p:? block-if-else-inline)
294 (p:? block-if-else-inline)
295 spaces?))
295 spaces?))
296
296
297 (p:defrule block-if-ml (and (and #\newline spaces?)
297 (p:defrule block-if-ml (and (and #\newline spaces?)
298 block-body
298 block-body
299 (p:? block-if-elseif)
299 (p:? block-if-elseif)
300 (p:? block-if-else)
300 (p:? block-if-else)
301 block-if-end)
301 block-if-end)
302 (:lambda (list)
302 (:lambda (list)
303 (cdr list)))
303 (cdr list)))
304
304
305 (p:defrule block-if-elseif-inline (and block-if-elseif-head line-body (p:? block-if-elseif-inline))
305 (p:defrule block-if-elseif-inline (and block-if-elseif-head line-body (p:? block-if-elseif-inline))
306 (:destructure (head statements elseif)
306 (:destructure (head statements elseif)
307 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
307 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
308
308
309 (p:defrule block-if-elseif (and block-if-elseif-head statement-end block-body (p:? block-if-elseif))
309 (p:defrule block-if-elseif (and block-if-elseif-head statement-end block-body (p:? block-if-elseif))
310 (:destructure (head ws statements elseif)
310 (:destructure (head ws statements elseif)
311 (declare (ignore ws))
311 (declare (ignore ws))
312 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
312 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
313
313
314 (p:defrule block-if-elseif-head (and (p:~ "elseif") spaces expression spaces? colon spaces?)
314 (p:defrule block-if-elseif-head (and (p:~ "elseif") spaces expression spaces? colon spaces?)
315 (:function remove-nil)
315 (:function remove-nil)
316 (:function intern-first))
316 (:function intern-first))
317
317
318 (p:defrule block-if-else-inline (and block-if-else-head line-body)
318 (p:defrule block-if-else-inline (and block-if-else-head line-body)
319 (:function second))
319 (:function second))
320
320
321 (p:defrule block-if-else (and block-if-else-head #\newline spaces? block-body)
321 (p:defrule block-if-else (and block-if-else-head #\newline spaces? block-body)
322 (:function fourth))
322 (:function fourth))
323
323
324 (p:defrule block-if-else-head (and (p:~ "else") spaces?)
324 (p:defrule block-if-else-head (and (p:~ "else") spaces?)
325 (:constant nil))
325 (:constant nil))
326
326
327 (p:defrule block-if-end (and (p:~ "end")
327 (p:defrule block-if-end (and (p:~ "end")
328 (p:? (and spaces (p:~ "if"))))
328 (p:? (and spaces (p:~ "if"))))
329 (:constant nil))
329 (:constant nil))
330
330
331 (p:defrule block-act (and block-act-head (or block-ml block-sl))
331 (p:defrule block-act (and block-act-head (or block-ml block-sl))
332 (:lambda (list)
332 (:lambda (list)
333 (apply #'append list)))
333 (apply #'append list)))
334
334
335 (p:defrule block-act-head (and (p:~ "act") spaces? qsp-string spaces?
335 (p:defrule block-act-head (and (p:~ "act") spaces? qsp-string spaces?
336 (p:? block-act-head-img)
336 (p:? block-act-head-img)
337 colon spaces?)
337 colon spaces?)
338 (:lambda (list)
338 (:lambda (list)
339 (intern-first (list (first list)
339 (intern-first (list (first list)
340 (third list)
340 (third list)
341 (or (fifth list) '(lib:str ""))))))
341 (or (fifth list) '(lib:str ""))))))
342
342
343 (p:defrule block-act-head-img (and #\, spaces? qsp-string spaces?)
343 (p:defrule block-act-head-img (and #\, spaces? qsp-string spaces?)
344 (:lambda (list)
344 (:lambda (list)
345 (or (third list) "")))
345 (or (third list) "")))
346
346
347 (p:defrule block-for (and block-for-head (or block-ml block-sl))
347 (p:defrule block-for (and block-for-head (or block-ml block-sl))
348 (:lambda (list)
348 (:lambda (list)
349 (apply #'append list)))
349 (apply #'append list)))
350
350
351 (p:defrule block-for-head (and (p:~ "for") spaces variable spaces? equal spaces? expression
351 (p:defrule block-for-head (and (p:~ "for") spaces variable spaces? equal spaces? expression
352 (p:~ "to") spaces expression
352 (p:~ "to") spaces expression
353 block-for-head-step
353 block-for-head-step
354 colon spaces?)
354 colon spaces?)
355 (:lambda (list)
355 (:lambda (list)
356 (list 'lib:qspfor
356 (list 'lib:qspfor
357 (elt list 2)
357 (elt list 2)
358 (elt list 6)
358 (elt list 6)
359 (elt list 9)
359 (elt list 9)
360 (elt list 10))))
360 (elt list 10))))
361
361
362 (p:defrule block-for-head-step (p:? (and (p:~ "step") spaces expression spaces?))
362 (p:defrule block-for-head-step (p:? (and (p:~ "step") spaces expression spaces?))
363 (:lambda (list)
363 (:lambda (list)
364 (if list
364 (if list
365 (third list)
365 (third list)
366 1)))
366 1)))
367
367
368 (p:defrule block-sl line-body)
368 (p:defrule block-sl line-body)
369
369
370 (p:defrule block-ml (and newline-block-body block-end)
370 (p:defrule block-ml (and newline-block-body block-end)
371 (:lambda (list)
371 (:lambda (list)
372 (apply #'list* (butlast list))))
372 (apply #'list* (butlast list))))
373
373
374 (p:defrule block-end (and (p:~ "end"))
374 (p:defrule block-end (and (p:~ "end"))
375 (:constant nil))
375 (:constant nil))
376
376
377 ;;; Calls
377 ;;; Calls
378
378
379 (p:defrule first-argument (and expression spaces?)
379 (p:defrule first-argument (and expression spaces?)
380 (:function first))
380 (:function first))
381 (p:defrule next-argument (and "," spaces? expression)
381 (p:defrule next-argument (and "," spaces? expression)
382 (:function third))
382 (:function third))
383 (p:defrule arguments (or parenthesized-arguments plain-arguments no-arguments))
383 (p:defrule arguments (or parenthesized-arguments plain-arguments no-arguments))
384 (p:defrule parenthesized-arguments (and spaces? #\( base-arguments #\))
384 (p:defrule parenthesized-arguments (and spaces? #\( base-arguments #\))
385 (:function third))
385 (:function third))
386 (p:defrule plain-arguments (and spaces? base-arguments)
386 (p:defrule plain-arguments (and spaces? base-arguments)
387 (:function second))
387 (:function second))
388 (p:defrule no-arguments (or (and spaces? (p:& #\newline))
388 (p:defrule no-arguments (or (and spaces? (p:& #\newline))
389 (and spaces? (p:& #\&))
389 (and spaces? (p:& #\&))
390 spaces?)
390 spaces?)
391 (:constant nil))
391 (:constant nil))
392 (p:defrule base-arguments (or (and first-argument (* next-argument)) spaces?)
392 (p:defrule base-arguments (or (and first-argument (* next-argument)) spaces?)
393 (:lambda (list)
393 (:lambda (list)
394 (if (null list)
394 (if (null list)
395 nil
395 nil
396 (list* (first list) (second list)))))
396 (list* (first list) (second list)))))
397
397
398 ;;; Intrinsics
398 ;;; Intrinsics
399
399
400 (defmacro defintrinsics ((rule-name returning-rule-name non-returning-rule-name) &body clauses)
400 (defmacro defintrinsics ((rule-name returning-rule-name non-returning-rule-name) &body clauses)
401 `(progn
401 `(progn
402 ,@(loop :for clause :in clauses
402 ,@(loop :for clause :in clauses
403 :collect `(defintrinsic ,@clause))
403 :collect `(defintrinsic ,@clause))
404 (p:defrule ,returning-rule-name (or ,@(remove-nil
404 (p:defrule ,returning-rule-name (or ,@(remove-nil
405 (mapcar (lambda (clause)
405 (mapcar (lambda (clause)
406 (when (second clause)
406 (when (second clause)
407 (alexandria:symbolicate
407 (alexandria:symbolicate
408 'intrinsic- (first clause))))
408 'intrinsic- (first clause))))
409 clauses))))
409 clauses))))
410 (p:defrule ,non-returning-rule-name (or ,@(remove-nil
410 (p:defrule ,non-returning-rule-name (or ,@(remove-nil
411 (mapcar (lambda (clause)
411 (mapcar (lambda (clause)
412 (unless (second clause)
412 (unless (second clause)
413 (alexandria:symbolicate
413 (alexandria:symbolicate
414 'intrinsic- (first clause))))
414 'intrinsic- (first clause))))
415 clauses))))
415 clauses))))
416 (p:defrule ,rule-name (or ,returning-rule-name ,non-returning-rule-name))))
416 (p:defrule ,rule-name (or ,returning-rule-name ,non-returning-rule-name))))
417
417
418 (defmacro defintrinsic (sym returning &optional (min-arity 0) max-arity &rest names)
418 (defmacro defintrinsic (sym returning &optional (min-arity 0) max-arity &rest names)
419 (declare (ignore returning))
419 (declare (ignore returning))
420 (unless max-arity
420 (unless max-arity
421 (setf max-arity *max-args*))
421 (setf max-arity *max-args*))
422 (setf names
422 (setf names
423 (if names
423 (if names
424 (mapcar #'string-upcase names)
424 (mapcar #'string-upcase names)
425 (list (string sym))))
425 (list (string sym))))
426 `(p:defrule ,(alexandria:symbolicate 'intrinsic- sym)
426 `(p:defrule ,(alexandria:symbolicate 'intrinsic- sym)
427 (and (p:? #\$) (or ,@(loop :for name :in names :collect `(p:~ ,name)))
427 (and (p:? #\$) (or ,@(loop :for name :in names :collect `(p:~ ,name)))
428 arguments)
428 arguments)
429 (:destructure (dollar name arguments)
429 (:destructure (dollar name arguments)
430 (declare (ignore dollar))
430 (declare (ignore dollar))
431 (unless (<= ,min-arity (length arguments) ,max-arity)
431 (unless (<= ,min-arity (length arguments) ,max-arity)
432 (error "Intrinsic ~A expects between ~A and ~A arguments but ~A were provided:~%~S"
432 (error "Intrinsic ~A expects between ~A and ~A arguments but ~A were provided:~%~S"
433 name ,min-arity ,max-arity (length arguments) arguments))
433 name ,min-arity ,max-arity (length arguments) arguments))
434 (list* ',(intern (string sym) "TXT2WEB.LIB") arguments))))
434 (list* ',(intern (string sym) "TXT2WEB.LIB") arguments))))
435
435
436 (defintrinsics (intrinsic returning-intrinsic non-returning-intrinsic)
436 (defintrinsics (intrinsic returning-intrinsic non-returning-intrinsic)
437 ;; Transitions
437 ;; Transitions
438 (goto% nil 0 nil "gt" "goto")
438 (goto% nil 0 nil "gt" "goto")
439 (xgoto% nil 0 nil "xgt" "xgoto")
439 (xgoto% nil 0 nil "xgt" "xgoto")
440 ;; Variables
440 ;; Variables
441 (killvar nil 0 2)
441 (killvar nil 0 2)
442 ;; Expressions
442 ;; Expressions
443 (obj t 1 1)
443 (obj t 1 1)
444 (loc t 1 1)
444 (loc t 1 1)
445 (no t 1 1)
445 (no t 1 1)
446 ;; Basic
446 ;; Basic
447 (qspver t 0 0)
447 (qspver t 0 0)
448 (curloc t 0 0)
448 (curloc t 0 0)
449 (rand t 1 2)
449 (rand t 1 2)
450 (rnd t 0 0)
450 (rnd t 0 0)
451 (qspmax t 1 nil "max")
451 (qspmax t 1 nil "max")
452 (qspmin t 1 nil "min")
452 (qspmin t 1 nil "min")
453 ;; Arrays
453 ;; Arrays
454 (killall nil 0 0)
454 (killall nil 0 0)
455 (copyarr nil 2 4)
455 (copyarr nil 2 4)
456 (arrsize t 1 1)
456 (arrsize t 1 1)
457 (arrpos t 2 3)
457 (arrpos t 2 3)
458 (arrcomp t 2 3)
458 (arrcomp t 2 3)
459 ;; Strings
459 ;; Strings
460 (len t 1 1)
460 (len t 1 1)
461 (mid t 2 3)
461 (mid t 2 3)
462 (ucase t 1 1)
462 (ucase t 1 1)
463 (lcase t 1 1)
463 (lcase t 1 1)
464 (trim t 1 1)
464 (trim t 1 1)
465 (replace t 2 3)
465 (qspreplace t 2 3 "replace")
466 (instr t 2 3)
466 (instr t 2 3)
467 (isnum t 1 1)
467 (isnum t 1 1)
468 (val t 1 1)
468 (val t 1 1)
469 (qspstr t 1 1 "str")
469 (qspstr t 1 1 "str")
470 (strcomp t 2 2)
470 (strcomp t 2 2)
471 (strfind t 2 3)
471 (strfind t 2 3)
472 (strpos t 2 3)
472 (strpos t 2 3)
473 ;; IF
473 ;; IF
474 (iif t 2 3)
474 (iif t 2 3)
475 ;; Subs
475 ;; Subs
476 (gosub nil 1 nil "gosub" "gs")
476 (gosub nil 1 nil "gosub" "gs")
477 (func t 1 nil)
477 (func t 1 nil)
478 (exit nil 0 0)
478 (exit nil 0 0)
479 ;; Jump
479 ;; Jump
480 (jump nil 1 1)
480 (jump nil 1 1)
481 ;; Dynamic
481 ;; Dynamic
482 (dynamic nil 1 nil)
482 (dynamic nil 1 nil)
483 (dyneval t 1 nil)
483 (dyneval t 1 nil)
484 ;; Sound
484 ;; Sound
485 (play nil 1 2)
485 (play nil 1 2)
486 (isplay t 1 1)
486 (isplay t 1 1)
487 (close nil 1 1)
487 (close nil 1 1)
488 (closeall nil 0 0 "close all")
488 (closeall nil 0 0 "close all")
489 ;; Main window
489 ;; Main window
490 (main-pl nil 1 1 "*pl")
490 (main-pl nil 1 1 "*pl")
491 (main-nl nil 0 1 "*nl")
491 (main-nl nil 0 1 "*nl")
492 (main-p nil 1 1 "*p")
492 (main-p nil 1 1 "*p")
493 (maintxt t 0 0)
493 (maintxt t 0 0)
494 (desc t 1 1)
494 (desc t 1 1)
495 (main-clear nil 0 0 "*clear" "*clr")
495 (main-clear nil 0 0 "*clear" "*clr")
496 ;; Aux window
496 ;; Aux window
497 (showstat nil 1 1)
497 (showstat nil 1 1)
498 (stat-pl nil 1 1 "pl")
498 (stat-pl nil 1 1 "pl")
499 (stat-nl nil 0 1 "nl")
499 (stat-nl nil 0 1 "nl")
500 (stat-p nil 1 1 "p")
500 (stat-p nil 1 1 "p")
501 (stattxt t 0 0)
501 (stattxt t 0 0)
502 (stat-clear nil 0 0 "clear" "clr")
502 (stat-clear nil 0 0 "clear" "clr")
503 (cls nil 0 0)
503 (cls nil 0 0)
504 ;; Dialog
504 ;; Dialog
505 (msg nil 1 1)
505 (msg nil 1 1)
506 ;; Acts
506 ;; Acts
507 (showacts nil 1 1)
507 (showacts nil 1 1)
508 (delact nil 1 1 "delact" "del act")
508 (delact nil 1 1 "delact" "del act")
509 (curacts t 0 0)
509 (curacts t 0 0)
510 (selact t 0 0)
510 (selact t 0 0)
511 (cla nil 0 0)
511 (cla nil 0 0)
512 ;; Objects
512 ;; Objects
513 (showobjs nil 1 1)
513 (showobjs nil 1 1)
514 (addobj nil 1 3 "addobj" "add obj")
514 (addobj nil 1 3 "addobj" "add obj")
515 (delobj nil 1 1 "delobj" "del obj")
515 (delobj nil 1 1 "delobj" "del obj")
516 (killobj nil 0 1)
516 (killobj nil 0 1)
517 (countobj t 0 0)
517 (countobj t 0 0)
518 (getobj t 1 1)
518 (getobj t 1 1)
519 (selobj t 0 0)
519 (selobj t 0 0)
520 ;; Menu
520 ;; Menu
521 (menu nil 1 1)
521 (menu nil 1 1)
522 ;; Images
522 ;; Images
523 (refint nil 0 0)
523 (refint nil 0 0)
524 (view nil 0 1)
524 (view nil 0 1)
525 (img nil 1)
525 (img nil 1)
526 (*img nil 1)
526 (*img nil 1)
527 ;; Fonts
527 ;; Fonts
528 (rgb t 3 3)
528 (rgb t 3 3)
529 ;; Input
529 ;; Input
530 (showinput nil 1 1)
530 (showinput nil 1 1)
531 (usertxt t 0 0 "user_text" "usrtxt")
531 (usertxt t 0 0 "user_text" "usrtxt")
532 (cmdclear nil 0 0 "cmdclear" "cmdclr")
532 (cmdclear nil 0 0 "cmdclear" "cmdclr")
533 (input t 1 1)
533 (input t 1 1)
534 ;; Files
534 ;; Files
535 (openqst nil 1 1)
535 (openqst nil 1 1)
536 (addqst nil 1 1 "addqst" "addlib" "inclib")
536 (addqst nil 1 1 "addqst" "addlib" "inclib")
537 (killqst nil 1 1 "killqst" "dellib" "freelib")
537 (killqst nil 1 1 "killqst" "dellib" "freelib")
538 (opengame nil 0 0)
538 (opengame nil 0 0)
539 (savegame nil 0 0)
539 (savegame nil 0 0)
540 ;; Real time
540 ;; Real time
541 (wait nil 1 1)
541 (wait nil 1 1)
542 (msecscount t 0 0)
542 (msecscount t 0 0)
543 (settimer nil 1 1))
543 (settimer nil 1 1))
544
544
545 ;;; Expression
545 ;;; Expression
546
546
547 (p:defrule expression or-expr)
547 (p:defrule expression or-expr)
548
548
549 (p:defrule or-expr (and and-expr (* (and spaces? or-op spaces? and-expr)))
549 (p:defrule or-expr (and and-expr (* (and spaces? or-op spaces? and-expr)))
550 (:function do-binop))
550 (:function do-binop))
551
551
552 (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr)))
552 (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr)))
553 (:function do-binop))
553 (:function do-binop))
554
554
555 (p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>"
555 (p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>"
556 "=" "<" ">" "!")
556 "=" "<" ">" "!")
557 spaces? sum-expr)))
557 spaces? sum-expr)))
558 (:function do-binop))
558 (:function do-binop))
559
559
560 (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr)))
560 (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr)))
561 (:function do-binop))
561 (:function do-binop))
562
562
563 (p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr)))
563 (p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr)))
564 (:function do-binop))
564 (:function do-binop))
565
565
566 (p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr)))
566 (p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr)))
567 (:function do-binop))
567 (:function do-binop))
568
568
569 (p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr)
569 (p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr)
570 (:lambda (list)
570 (:lambda (list)
571 (let ((expr (remove-nil list)))
571 (let ((expr (remove-nil list)))
572 (if (= 1 (length expr))
572 (if (= 1 (length expr))
573 (first expr)
573 (first expr)
574 (intern-first expr)))))
574 (intern-first expr)))))
575
575
576 (p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr) spaces?)
576 (p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr) spaces?)
577 (:function first))
577 (:function first))
578
578
579 (p:defrule paren-expr (and #\( spaces? expression spaces? #\))
579 (p:defrule paren-expr (and #\( spaces? expression spaces? #\))
580 (:function third))
580 (:function third))
581
581
582 (p:defrule or-op (p:~ "or")
582 (p:defrule or-op (p:~ "or")
583 (:constant "or"))
583 (:constant "or"))
584
584
585 (p:defrule and-op (p:~ "and")
585 (p:defrule and-op (p:~ "and")
586 (:constant "and"))
586 (:constant "and"))
587
587
588 ;;; Variables
588 ;;; Variables
589
589
590 (p:defrule variable (and identifier (p:? array-index))
590 (p:defrule variable (and identifier (p:? array-index))
591 (:destructure (id idx-raw)
591 (:destructure (id idx-raw)
592 (let ((idx (case idx-raw
592 (let ((idx (case idx-raw
593 ((nil) 0)
593 ((nil) 0)
594 (:last nil)
594 (:last nil)
595 (t idx-raw))))
595 (t idx-raw))))
596 (list 'lib:qspvar id idx))))
596 (list 'lib:qspvar id idx))))
597
597
598 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
598 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
599 (:lambda (list)
599 (:lambda (list)
600 (or (third list) :last)))
600 (or (third list) :last)))
601
601
602 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
602 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
603 (:destructure (qspvar eq expr)
603 (:destructure (qspvar eq expr)
604 (declare (ignore eq))
604 (declare (ignore eq))
605 (list 'lib:set qspvar expr)))
605 (list 'lib:set qspvar expr)))
606
606
607 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? (or op-assignment plain-assignment))
607 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? (or op-assignment plain-assignment))
608 (:function third))
608 (:function third))
609
609
610 (p:defrule op-assignment (and variable spaces? (or "+" "-" "*" "/") #\= spaces? expression)
610 (p:defrule op-assignment (and variable spaces? (or "+" "-" "*" "/") #\= spaces? expression)
611 (:destructure (qspvar ws1 op eq ws2 expr)
611 (:destructure (qspvar ws1 op eq ws2 expr)
612 (declare (ignore ws1 ws2))
612 (declare (ignore ws1 ws2))
613 (list qspvar eq (intern-first (list op qspvar expr)))))
613 (list qspvar eq (intern-first (list op qspvar expr)))))
614
614
615 (p:defrule plain-assignment (and variable spaces? #\= spaces? expression)
615 (p:defrule plain-assignment (and variable spaces? #\= spaces? expression)
616 (:function remove-nil))
616 (:function remove-nil))
617
617
618 ;;; Non-string literals
618 ;;; Non-string literals
619
619
620 (p:defrule literal (or qsp-string brace-string number))
620 (p:defrule literal (or qsp-string brace-string number))
621
621
622 (p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
622 (p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
623 (:lambda (list)
623 (:lambda (list)
624 (parse-integer (p:text list))))
624 (parse-integer (p:text list))))
@@ -1,74 +1,74 b''
1
1
2 (in-package parenscript)
2 (in-package parenscript)
3
3
4 ;;; async/await
4 ;;; async/await
5
5
6 (defprinter ps-js::await (x)
6 (defprinter ps-js::await (x)
7 (psw (string-downcase "await "))
7 (psw (string-downcase "await "))
8 (print-op-argument 'ps-js::await x))
8 (print-op-argument 'ps-js::await x))
9
9
10 (define-trivial-special-ops await ps-js::await)
10 (define-trivial-special-ops await ps-js::await)
11
11
12 (define-statement-operator async-defun (name lambda-list &rest body)
12 (define-statement-operator async-defun (name lambda-list &rest body)
13 (multiple-value-bind (effective-args body-block docstring)
13 (multiple-value-bind (effective-args body-block docstring)
14 (compile-named-function-body name lambda-list body)
14 (compile-named-function-body name lambda-list body)
15 (list 'ps-js::async-defun name effective-args docstring body-block)))
15 (list 'ps-js::async-defun name effective-args docstring body-block)))
16
16
17 (defprinter ps-js::async-defun (name args docstring body-block)
17 (defprinter ps-js::async-defun (name args docstring body-block)
18 (when docstring (print-comment docstring))
18 (when docstring (print-comment docstring))
19 (psw "async ")
19 (psw "async ")
20 (print-fun-def name args body-block))
20 (print-fun-def name args body-block))
21
21
22 (define-expression-operator async-lambda (lambda-list &rest body)
22 (define-expression-operator async-lambda (lambda-list &rest body)
23 (multiple-value-bind (effective-args effective-body)
23 (multiple-value-bind (effective-args effective-body)
24 (parse-extended-function lambda-list body)
24 (parse-extended-function lambda-list body)
25 `(ps-js::async-lambda
25 `(ps-js::async-lambda
26 ,effective-args
26 ,effective-args
27 ,(let ((*function-block-names* ()))
27 ,(let ((*function-block-names* ()))
28 (compile-function-body effective-args effective-body)))))
28 (compile-function-body effective-args effective-body)))))
29
29
30 (defprinter ps-js::async-lambda (args body-block)
30 (defprinter ps-js::async-lambda (args body-block)
31 (psw "async ")
31 (psw "async ")
32 (print-fun-def nil args body-block))
32 (print-fun-def nil args body-block))
33
33
34 (cl:export 'await)
34 (cl:export 'await)
35 (cl:export 'async-defun)
35 (cl:export 'async-defun)
36 (cl:export 'async-lambda)
36 (cl:export 'async-lambda)
37
37
38 ;;; ES6
38 ;;; ES6
39
39
40 (define-expression-operator => (lambda-list &rest body)
40 (define-expression-operator => (lambda-list &rest body)
41 (unless (listp lambda-list)
41 (unless (listp lambda-list)
42 (setf lambda-list (list lambda-list)))
42 (setf lambda-list (list lambda-list)))
43 (multiple-value-bind (effective-args effective-body)
43 (multiple-value-bind (effective-args effective-body)
44 (parse-extended-function lambda-list body)
44 (parse-extended-function lambda-list body)
45 `(ps-js::=>
45 `(ps-js::=>
46 ,effective-args
46 ,effective-args
47 ,(let ((*function-block-names* ()))
47 ,(let ((*function-block-names* ()))
48 (compile-function-body effective-args effective-body)))))
48 (compile-function-body effective-args effective-body)))))
49
49
50 (defprinter ps-js::=> (args body)
50 (defprinter ps-js::=> (args body)
51 (unless (= 1 (length args))
51 (unless (= 1 (length args))
52 (psw "("))
52 (psw "("))
53 (loop for (arg . remaining) on args do
53 (loop for (arg . remaining) on args do
54 (psw (symbol-to-js-string arg)) (when remaining (psw ", ")))
54 (psw (symbol-to-js-string arg)) (when remaining (psw ", ")))
55 (unless (= 1 (length args))
55 (unless (= 1 (length args))
56 (psw ")"))
56 (psw ")"))
57 (psw " => ")
57 (psw " => ")
58 (ps-print body))
58 (ps-print body))
59
59
60 (cl:export '=>)
60 (cl:export '=>)
61
61
62 ;;; Actually return nothing (with no empty return)
62 ;;; Actually return nothing (with no empty return)
63 (defvar *old-return-result-of* (function return-result-of))
63 (defvar *old-return-result-of* (function return-result-of))
64
64
65 (defun return-result-of (tag form)
65 (defun return-result-of (tag form)
66 (if (equal form '(void))
66 (if (equal form '(void))
67 nil
67 nil
68 (funcall *old-return-result-of* tag form)))
68 (funcall *old-return-result-of* tag form)))
69 (export 'void)
69 (cl:export 'void)
70
70
71 ;;; Bitwise stuff
71 ;;; Bitwise stuff
72 ;; No idea why these are not exported
72 ;; No idea why these are not exported
73 (export '<<)
73 (export '<<)
74 (export '>>)
74 (export '>>)
General Comments 0
You need to be logged in to leave comments. Login now