##// END OF EJS Templates
A few parser fixes
naryl -
r13:f0a3bfeb default
parent child Browse files
Show More
@@ -1,44 +1,44 b''
1 1 (инструкции на Русском - внизу)
2 2
3 3 # sugar-qsp
4 4 Compiler for QSP games which creates monolithic HTML pages.
5 5
6 6 ## Usage
7 7
8 8 There are three mastery levels
9 9
10 10 1. Just build me the game:<br/>
11 11 `sugar-qsp game.txt`<br/>
12 12 And it will create the game in game.html
13 13
14 14 2. I know what I'm doing:<br/>
15 15 `sugar-qsp game.txt -o game.html --body body.html --js jquery.js my-js-library.js --css styles/*.css`<br/>
16 16 All options are self-explanatory. The result is a monolithic html specified
17 17 with the `-o` option. Default `body.html` (used by the first mastery level) can
18 18 be found in `extas` directory.
19 19
20 20 3. I'm a frontend developer!<br/>
21 21 `sugar-qsp game.txt -c -o game.js`<br/>
22 22 It just builds the game script into a js you can put on your website. To run
23 23 the game execute `SugarQSP.start()`
24 24
25 25 # sugar-qsp
26 26 Компилятор для игр на QSP создающий монолитные страницы на HTML.
27 27
28 28 ## Инструкции
29 29
30 30 Есть три уровня мастерства.
31 31
32 32 1. **Просто собери мне игру**:<br/>
33 33 `sugar-qsp game.txt`<br/>
34 34 Создаст игру в game.html
35 35
36 36 2. **Я знаю что делаю**:<br/>
37 37 `sugar-qsp game.txt -o game.html --body body.html --js jquery.js my-js-library.js --css styles/*.css`<br/>
38 Если вы знаете что делаете, то для вас смысл опций очевиден. `body.html`
39 по-умолчанию лежит в каталоге `extras`.
38 Если вы знаете что делаете, то для вас смысл опций очевиден. `body.html` и `default.css`
39 лежат в каталоге `extras`.
40 40
41 41 3. **Я - фронтендер!**<br/>
42 42 `sugar-qsp game.txt -c -o game.js`<br/>
43 43 Просто соберёт игру в Javascript файл который вы можете разместить на своём
44 сайте как вам угодно. Для запуска игры вызовите `SugarQSP.start()`.
44 сайте как вам угодно.
@@ -1,140 +1,144 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;;; Macros implementing some intrinsics where it makes sense
5 5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6 6
7 7 ;;; 1loc
8 8
9 9 ;;; 2var
10 10
11 11 (ps:defpsmacro killvar (varname &optional (index :whole))
12 12 `(api-call kill-var ,varname ,index))
13 13
14 14 (ps:defpsmacro killall ()
15 15 `(api-call kill-all))
16 16
17 17 ;;; 3expr
18 18
19 19 (ps:defpsmacro obj (name)
20 20 `(funcall (root objs includes) ,name))
21 21
22 22 (ps:defpsmacro loc (name)
23 23 `(funcall (root locs includes) ,name))
24 24
25 25 (ps:defpsmacro no (arg)
26 26 `(- -1 ,arg))
27 27
28 28 ;;; 4code
29 29
30 30 (ps:defpsmacro qspver ()
31 31 "0.0.1")
32 32
33 33 (ps:defpsmacro curloc ()
34 34 `(root current-location))
35 35
36 36 (ps:defpsmacro rnd ()
37 37 `(funcall (root lib rand) 1 1000))
38 38
39 39 (ps:defpsmacro qspmax (&rest args)
40 `(max ,@args))
40 (if (= 1 (length args))
41 `(*math.max.apply nil ,@args)
42 `(*math.max ,@args)))
41 43
42 44 (ps:defpsmacro qspmin (&rest args)
43 `(min ,@args))
45 (if (= 1 (length args))
46 `(*math.min.apply nil ,@args)
47 `(*math.min ,@args)))
44 48
45 49 ;;; 5arrays
46 50
47 51 (ps:defpsmacro arrsize (name)
48 52 `(api-call array-size ,name))
49 53
50 54 ;;; 6str
51 55
52 56 (ps:defpsmacro len (s)
53 57 `(length ,s))
54 58
55 59 (ps:defpsmacro mid (s from &optional count)
56 60 `(ps:chain ,s (substring ,from ,count)))
57 61
58 62 (ps:defpsmacro ucase (s)
59 63 `(ps:chain ,s (to-upper-case)))
60 64
61 65 (ps:defpsmacro lcase (s)
62 66 `(ps:chain ,s (to-lower-case)))
63 67
64 68 (ps:defpsmacro trim (s)
65 69 `(ps:chain ,s (trim)))
66 70
67 71 (ps:defpsmacro replace (s from to)
68 72 `(ps:chain ,s (replace ,from ,to)))
69 73
70 74 (ps:defpsmacro val (s)
71 75 `(parse-int ,s 10))
72 76
73 77 (ps:defpsmacro qspstr (n)
74 78 `(ps:chain ,n (to-string)))
75 79
76 80 ;;; 7if
77 81
78 82 ;;; 8sub
79 83
80 84 ;;; 9loops
81 85
82 86 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
83 87
84 88 (ps:defpsmacro exit ()
85 89 `(return-from nil (values)))
86 90
87 91 ;;; 10dynamic
88 92
89 93 ;;; 11main
90 94
91 95 (ps:defpsmacro desc (s)
92 96 (declare (ignore s))
93 97 "")
94 98
95 99 ;;; 12stat
96 100
97 101 (ps:defpsmacro showstat (enable)
98 102 `(api-call enable-frame :stat ,enable))
99 103
100 104 ;;; 13diag
101 105
102 106 (ps:defpsmacro msg (text)
103 107 `(alert ,text))
104 108
105 109 ;;; 14act
106 110
107 111 (ps:defpsmacro showacts (enable)
108 112 `(api-call enable-frame :acts ,enable))
109 113
110 114 (ps:defpsmacro delact (name)
111 115 `(api-call del-act ,name))
112 116
113 117 (ps:defpsmacro cla ()
114 118 `(api-call clear-act))
115 119
116 120 ;;; 15objs
117 121
118 122 (ps:defpsmacro showobjs (enable)
119 123 `(api-call enable-frame :objs ,enable))
120 124
121 125 (ps:defpsmacro countobj ()
122 126 `(length (root objs)))
123 127
124 128 (ps:defpsmacro getobj (index)
125 129 `(or (elt (root objs) ,index) ""))
126 130
127 131 ;;; 16menu
128 132
129 133 ;;; 17sound
130 134
131 135 (ps:defpsmacro isplay (filename)
132 136 `(funcall (root playing includes) ,filename))
133 137
134 138 ;;; 18img
135 139
136 140 ;;; 19input
137 141
138 142 ;;; 20time
139 143
140 144 ;;; misc
@@ -1,571 +1,580 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;;; Parses TXT source to an intermediate representation
5 5
6 6 ;;; Utility
7 7
8 8 (defun remove-nth (list nth)
9 9 (append (subseq list 0 nth)
10 10 (subseq list (1+ nth))))
11 11
12 12 (defun not-quote (char)
13 13 (not (eql #\' char)))
14 14
15 15
16 16 (defun not-doublequote (char)
17 17 (not (eql #\" char)))
18 18
19 19 (defun not-brace (char)
20 20 (not (eql #\} char)))
21 21
22 22 (defun not-integer (string)
23 23 (when (find-if-not #'digit-char-p string)
24 24 t))
25 25
26 26 (defun not-newline (char)
27 27 (not (eql #\newline char)))
28 28
29 29 (defun id-any-char (char)
30 30 (and
31 31 (not (digit-char-p char))
32 32 (not (eql #\newline char))
33 33 (not (find char " !:&=<>+-*/,'\"()[]{}"))))
34 34
35 35 (defun intern-first (list)
36 36 (list* (intern (string-upcase (first list)))
37 37 (rest list)))
38 38
39 39 (eval-when (:compile-toplevel :load-toplevel :execute)
40 40 (defun remove-nil (list)
41 41 (remove nil list)))
42 42
43 43 (defun binop-rest (list)
44 44 (destructuring-bind (ws1 operator ws2 operand2)
45 45 list
46 46 (declare (ignore ws1 ws2))
47 47 (list (intern (string-upcase operator)) operand2)))
48 48
49 49 (defun do-binop% (left-op other-ops)
50 50 (if (null other-ops)
51 51 left-op
52 52 (destructuring-bind ((operator right-op) &rest rest-ops)
53 53 other-ops
54 54 (if (and (listp left-op)
55 55 (eq (first left-op)
56 56 operator))
57 57 (do-binop% (append left-op (list right-op)) rest-ops)
58 58 (do-binop% (list operator left-op right-op) rest-ops)))))
59 59
60 60 (defun do-binop (list)
61 61 (destructuring-bind (left-op rest-ops)
62 62 list
63 63 (do-binop% left-op
64 64 (mapcar #'binop-rest rest-ops))))
65 65
66 66 (p:defrule line-continuation (and #\_ #\newline)
67 67 (:constant nil))
68 68
69 69 (p:defrule text-spaces (+ (or #\space #\tab line-continuation))
70 70 (:text t))
71 71
72 72 (p:defrule spaces (+ (or #\space #\tab line-continuation))
73 73 (:constant nil))
74 74
75 75 (p:defrule spaces? (* (or #\space #\tab line-continuation))
76 76 (:constant nil))
77 77
78 78 (p:defrule colon #\:
79 79 (:constant nil))
80 80
81 81 (p:defrule alphanumeric (alphanumericp character))
82 82
83 83 (p:defrule not-newline (not-newline character))
84 84
85 85 (p:defrule squote-esc "''"
86 86 (:lambda (list)
87 87 (p:text (elt list 0))))
88 88
89 89 (p:defrule dquote-esc "\"\""
90 90 (:lambda (list)
91 91 (p:text (elt list 0))))
92 92
93 93 (p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:")))
94 94 (or squote-esc (not-quote character))))
95 95 (:lambda (list)
96 96 (p:text (mapcar #'second list))))
97 97
98 98 (p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:")))
99 99 (or dquote-esc (not-doublequote character))))
100 100 (:lambda (list)
101 101 (p:text (mapcar #'second list))))
102 102
103 103 ;;; Identifiers
104 104
105 105 ;; From the official docs
106 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr $counter countobj $curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit fcolor $fname freelib fsize func getobj gosub goto gs gt if iif inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc $maintxt max menu mid min mod msecscount msg nl *nl no nosave obj $onactsel $ongload $ongsave $onnewloc $onobjadd $onobjdel $onobjsel opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat $stattxt str strcomp strfind strpos trim ucase unsel unselect $usercom user_text usrtxt val view wait xgoto xgt))
106 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit fcolor fname freelib fsize func getobj gosub goto gs gt if iif inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc maintxt max menu mid min mod msecscount msg nl *nl no nosave obj onactsel ongload ongsave onnewloc onobjadd onobjdel onobjsel opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt str strcomp strfind strpos trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
107
108 (defun trim-$ (str)
109 (if (char= #\$ (elt str 0))
110 (subseq str 1)
111 str))
107 112
108 113 (defun qsp-keyword-p (id)
109 (member (intern (string-upcase id)) *keywords*))
114 (member (intern (trim-$ (string-upcase id))) *keywords*))
110 115
111 116 (defun not-qsp-keyword-p (id)
112 (not (member (intern (string-upcase id)) *keywords*)))
117 (not (member (intern (trim-$ (string-upcase id))) *keywords*)))
113 118
114 119 (p:defrule qsp-keyword (qsp-keyword-p identifier-raw))
115 120
116 121 (p:defrule id-first (id-any-char character))
117 122 (p:defrule id-next (or (id-any-char character)
118 123 (digit-char-p character)))
119 124 (p:defrule identifier-raw (and id-first (* id-next))
120 125 (:lambda (list)
121 (let ((id (p:text list)))
122 (when (member id *keywords*)
123 (error "~A is a keyword" id))
124 (intern (string-upcase id)))))
126 (intern (string-upcase (p:text list)))))
125 127
126 128 (p:defrule identifier (not-qsp-keyword-p identifier-raw))
127 129
128 130 ;;; Strings
129 131
130 132 (p:defrule qsp-string (or normal-string brace-string))
131 133
132 134 (p:defrule normal-string (or sstring dstring)
133 135 (:lambda (str)
134 136 (list* 'str (or str (list "")))))
135 137
136 138 (p:defrule sstring (and #\' (* (or string-interpol
137 139 sstring-exec
138 140 sstring-chars))
139 141 #\')
140 142 (:function second))
141 143
142 144 (p:defrule dstring (and #\" (* (or string-interpol
143 145 dstring-exec
144 146 dstring-chars))
145 147 #\")
146 148 (:function second))
147 149
148 150 (p:defrule string-interpol (and "<<" expression ">>")
149 151 (:function second))
150 152
151 153 (p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character)))
152 154 (:text t))
153 155
154 156 (p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character)))
155 157 (:text t))
156 158
157 159 (p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\")
158 160 (:lambda (list)
159 161 (list* 'exec (p:parse 'exec-body (second list)))))
160 162
161 163 (p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\')
162 164 (:lambda (list)
163 165 (list* 'exec (p:parse 'exec-body (second list)))))
164 166
165 167 (p:defrule brace-string (and #\{ before-statement block-body #\})
166 168 (:lambda (list)
167 169 (list* 'qspblock (third list))))
168 170
169 171 ;;; Location
170 172
171 173 (p:defrule sugar-qsp-grammar (and (* (or spaces #\newline))
172 174 (* location))
173 175 (:function second))
174 176
175 177 (p:defrule location (and location-header block-body location-end)
176 178 (:destructure (header body end)
177 179 (declare (ignore end))
178 180 `(location (,header) ,@body)))
179 181
180 182 (p:defrule location-header (and #\#
181 183 (+ not-newline)
182 184 (and #\newline spaces? before-statement))
183 185 (:destructure (spaces1 name spaces2)
184 186 (declare (ignore spaces1 spaces2))
185 187 (string-upcase (string-trim " " (p:text name)))))
186 188
187 189 (p:defrule location-end (and #\- (* not-newline) #\newline before-statement)
188 190 (:constant nil))
189 191
190 192 ;;; Block body
191 193
192 194 (p:defrule newline-block-body (and #\newline spaces? block-body)
193 195 (:function third))
194 196
195 197 (p:defrule block-body (* statement)
196 198 (:function remove-nil))
197 199
198 200 ;; Just for <a href="exec:...'>
199 201 ;; Explicitly called from that rule's production
200 202 (p:defrule exec-body (and before-statement line-body)
201 203 (:function second))
202 204
203 205 (p:defrule line-body (and inline-statement (* next-inline-statement))
204 206 (:lambda (list)
205 207 (list* (first list) (second list))))
206 208
207 209 (p:defrule before-statement (* (or #\newline spaces))
208 210 (:constant nil))
209 211
210 212 (p:defrule statement-end (or statement-end-real statement-end-block-close))
211 213
212 214 (p:defrule statement-end-real (and (or #\newline
213 215 (and #\& spaces? (p:& statement%)))
214 216 before-statement)
215 217 (:constant nil))
216 218
217 219 (p:defrule statement-end-block-close (or (p:& #\}))
218 220 (:constant nil))
219 221
220 222 (p:defrule inline-statement (and statement% spaces?)
221 223 (:function first))
222 224
223 225 (p:defrule next-inline-statement (and #\& spaces? inline-statement)
224 226 (:function third))
225 227
226 228 (p:defrule not-a-non-statement (and (p:! (p:~ "elseif"))
227 229 (p:! (p:~ "else"))
228 230 (p:! (p:~ "end"))))
229 231
230 232 (p:defrule statement (and inline-statement statement-end)
231 233 (:function first))
232 234
233 235 (p:defrule statement% (and not-a-non-statement
234 236 (or label comment string-output
235 237 block non-returning-intrinsic assignment
236 238 expression-output))
237 239 (:function second))
238 240
239 241 (p:defrule expr-stopper (or comment block non-returning-intrinsic))
240 242
241 243 (p:defrule string-output qsp-string
242 244 (:lambda (string)
243 245 (list 'main-pl string)))
244 246
245 247 (p:defrule expression-output expression
246 248 (:lambda (list)
247 249 (list 'main-pl list)))
248 250
249 251 (p:defrule label (and colon identifier)
250 252 (:lambda (list)
251 253 (intern (string (second list)) :keyword)))
252 254
253 (p:defrule comment (and #\! (* (or text-spaces qsp-string brace-string not-newline)))
255 (p:defrule comment (and #\! (* (or qsp-string brace-comment text-spaces not-newline)))
256 (:constant nil))
257
258 (p:defrule brace-comment (and #\{ (* (not-brace character)) #\})
254 259 (:constant nil))
255 260
256 261 ;;; Blocks
257 262
258 263 (p:defrule block (or block-act block-if))
259 264
260 265 (p:defrule block-if (and block-if-head block-if-body)
261 266 (:destructure (head body)
262 267 `(qspcond (,@head ,@(first body))
263 268 ,@(rest body))))
264 269
265 270 (p:defrule block-if-head (and (p:~ "if") spaces expression spaces? colon spaces?)
266 271 (:function remove-nil)
267 272 (:function cdr))
268 273
269 274 (p:defrule block-if-body (or block-if-ml block-if-sl)
270 275 (:destructure (if-body elseifs else &rest ws)
271 276 (declare (ignore ws))
272 277 `(,(remove-nil if-body) ,@elseifs ,@(when else `((else ,@else))))))
273 278
274 279 (p:defrule block-if-sl (and line-body
275 280 (p:? block-if-elseif-inline)
276 281 (p:? block-if-else-inline)
277 282 spaces?))
278 283
279 284 (p:defrule block-if-ml (and (and #\newline spaces?)
280 285 block-body
281 286 (p:? block-if-elseif)
282 287 (p:? block-if-else)
283 288 block-if-end)
284 289 (:lambda (list)
285 290 (cdr list)))
286 291
287 292 (p:defrule block-if-elseif-inline (and block-if-elseif-head line-body (p:? block-if-elseif-inline))
288 293 (:destructure (head statements elseif)
289 294 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
290 295
291 296 (p:defrule block-if-elseif (and block-if-elseif-head statement-end block-body (p:? block-if-elseif))
292 297 (:destructure (head ws statements elseif)
293 298 (declare (ignore ws))
294 299 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
295 300
296 301 (p:defrule block-if-elseif-head (and (p:~ "elseif") spaces expression spaces? colon spaces?)
297 302 (:function remove-nil)
298 303 (:function intern-first))
299 304
300 305 (p:defrule block-if-else-inline (and block-if-else-head line-body)
301 306 (:function second))
302 307
303 308 (p:defrule block-if-else (and block-if-else-head #\newline spaces? block-body)
304 309 (:function fourth))
305 310
306 311 (p:defrule block-if-else-head (and (p:~ "else") spaces?)
307 312 (:constant nil))
308 313
309 314 (p:defrule block-if-end (and (p:~ "end")
310 315 (p:? (and spaces (p:~ "if"))))
311 316 (:constant nil))
312 317
313 318 (p:defrule block-act (and block-act-head (or block-act-ml block-act-sl))
314 319 (:lambda (list)
315 320 (apply #'append list)))
316 321
317 322 (p:defrule block-act-sl line-body)
318 323
319 324 (p:defrule block-act-ml (and newline-block-body block-act-end)
320 325 (:lambda (list)
321 326 (apply #'list* (butlast list))))
322 327
323 328 (p:defrule block-act-head (and (p:~ "act") spaces qsp-string spaces?
324 329 (p:? block-act-head-img)
325 330 colon spaces?)
326 331 (:lambda (list)
327 332 (intern-first (list (first list)
328 333 (third list)
329 334 (or (fifth list) '(str ""))))))
330 335
331 336 (p:defrule block-act-head-img (and #\, spaces? qsp-string spaces?)
332 337 (:lambda (list)
333 338 (or (third list) "")))
334 339
335 340 (p:defrule block-act-end (and (p:~ "end"))
336 341 (:constant nil))
337 342
338 343 ;;; Calls
339 344
340 345 (p:defrule first-argument (and expression spaces?)
341 346 (:function first))
342 347 (p:defrule next-argument (and "," spaces? expression)
343 348 (:function third))
344 349 (p:defrule arguments (or parenthesized-arguments plain-arguments no-arguments))
345 350 (p:defrule parenthesized-arguments (and spaces? #\( base-arguments #\))
346 351 (:function third))
347 352 (p:defrule plain-arguments (and spaces base-arguments)
348 353 (:function second))
349 (p:defrule no-arguments (or spaces (p:& #\newline) (p:& #\&))
354 (p:defrule no-arguments (or (and spaces? (p:& #\newline))
355 (and spaces? (p:& #\&))
356 spaces?)
350 357 (:constant nil))
351 (p:defrule base-arguments (and first-argument (* next-argument))
352 (:destructure (first rest)
353 (list* first rest)))
358 (p:defrule base-arguments (or (and first-argument (* next-argument)) spaces?)
359 (:lambda (list)
360 (if (null list)
361 nil
362 (list* (first list) (second list)))))
354 363
355 364 ;;; Intrinsics
356 365
357 366 (defmacro defintrinsics ((rule-name returning-rule-name non-returning-rule-name) &body clauses)
358 367 `(progn
359 368 ,@(loop :for clause :in clauses
360 369 :collect `(defintrinsic ,@clause))
361 370 (p:defrule ,returning-rule-name (or ,@(remove-nil
362 371 (mapcar (lambda (clause)
363 372 (when (second clause)
364 373 (alexandria:symbolicate
365 374 'intrinsic- (first clause))))
366 375 clauses))))
367 376 (p:defrule ,non-returning-rule-name (or ,@(remove-nil
368 377 (mapcar (lambda (clause)
369 378 (unless (second clause)
370 379 (alexandria:symbolicate
371 380 'intrinsic- (first clause))))
372 381 clauses))))
373 382 (p:defrule ,rule-name (or ,returning-rule-name ,non-returning-rule-name))))
374 383
375 384 (defmacro defintrinsic (sym returning &optional (min-arity 0) (max-arity 10) &rest names)
376 385 (declare (ignore returning))
377 386 (setf names
378 387 (if names
379 388 (mapcar #'string-upcase names)
380 389 (list (string sym))))
381 390 `(p:defrule ,(alexandria:symbolicate 'intrinsic- sym)
382 391 (and (p:? #\$) (or ,@(loop :for name :in names :collect `(p:~ ,name)))
383 392 arguments)
384 393 (:destructure (dollar name arguments)
385 394 (declare (ignore dollar))
386 395 (unless (<= ,min-arity (length arguments) ,max-arity)
387 396 (error "Intrinsic ~A expects between ~A and ~A arguments but ~A were provided:~%~S"
388 397 name ,min-arity ,max-arity (length arguments) arguments))
389 398 (list* ',sym arguments))))
390 399
391 400 (defintrinsics (intrinsic returning-intrinsic non-returning-intrinsic)
392 401 ;; Transitions
393 402 (goto nil 0 10 "gt" "goto")
394 403 (xgoto nil 0 10 "xgt" "xgoto")
395 404 ;; Variables
396 405 (killvar nil 0 2)
397 406 ;; Expressions
398 407 (obj t 1 1)
399 408 (loc t 1 1)
400 409 (no t 1 1)
401 410 ;; Basic
402 411 (qspver t 0 0)
403 412 (curloc t 0 0)
404 413 (rand t 1 2)
405 414 (rnd t 0 0)
406 415 (qspmax t 1 10 "max")
407 416 (qspmin t 1 10 "min")
408 417 ;; Arrays
409 418 (killall nil 0 0)
410 419 (copyarr nil 2 4)
411 420 (arrsize t 1 1)
412 421 (arrpos t 2 3)
413 422 (arrcomp t 2 3)
414 423 ;; Strings
415 424 (len t 1 1)
416 425 (mid t 2 3)
417 426 (ucase t 1 1)
418 427 (lcase t 1 1)
419 428 (trim t 1 1)
420 429 (replace t 2 3)
421 430 (instr t 2 3)
422 431 (isnum t 1 1)
423 432 (val t 1 1)
424 433 (qspstr t 1 1 "str")
425 434 (strcomp t 2 2)
426 435 (strfind t 2 3)
427 436 (strpos t 2 3)
428 437 ;; IF
429 438 (iif t 2 3)
430 439 ;; Subs
431 440 (gosub nil 1 10 "gosub" "gs")
432 441 (func t 1 10)
433 442 (exit nil 0 0)
434 443 ;; Jump
435 444 (jump nil 1 1)
436 445 ;; Dynamic
437 446 (dynamic nil 1 10)
438 447 (dyneval t 1 10)
439 448 ;; Main window
440 (main-p nil 1 1 "*p")
441 449 (main-pl nil 1 1 "*pl")
442 450 (main-nl nil 0 1 "*nl")
451 (main-p nil 1 1 "*p")
443 452 (maintxt t 0 0)
444 453 (desc t 1 1)
445 454 (main-clear nil 0 0 "*clear" "*clr")
446 455 ;; Aux window
447 456 (showstat nil 1 1)
448 (stat-p nil 1 1 "p")
449 457 (stat-pl nil 1 1 "pl")
450 458 (stat-nl nil 0 1 "nl")
459 (stat-p nil 1 1 "p")
451 460 (stattxt t 0 0)
452 461 (stat-clear nil 0 0 "clear" "clr")
453 462 (cls nil 0 0)
454 463 ;; Dialog
455 464 (msg nil 1 1)
456 465 ;; Acts
457 466 (showacts nil 1 1)
458 467 (delact nil 1 1 "delact" "del act")
459 468 (curacts t 0 0)
460 469 (cla nil 0 0)
461 470 ;; Objects
462 471 (showobjs nil 1 1)
463 472 (addobj nil 1 3 "addobj" "add obj")
464 473 (delobj nil 1 1 "delobj" "del obj")
465 474 (killobj nil 0 1)
466 475 (countobj t 0 0)
467 476 (getobj t 1 1)
468 477 ;; Menu
469 478 (menu nil 1 1)
470 479 ;; Sound
471 480 (play nil 1 2)
472 481 (isplay t 1 1)
473 482 (close nil 1 1)
474 483 (closeall nil 0 0 "close all")
475 484 ;; Images
476 485 (refint nil 0 0)
477 486 (view nil 0 1)
478 487 ;; Fonts
479 488 (rgb t 3 3)
480 489 ;; Input
481 490 (showinput nil 1 1)
482 491 (usertxt t 0 0 "user_text" "usrtxt")
483 492 (cmdclear nil 0 0 "cmdclear" "cmdclr")
484 493 (input t 1 1)
485 494 ;; Files
486 495 (openqst nil 1 1)
487 496 (addqst nil 1 1 "addqst" "addlib" "inclib")
488 497 (killqst nil 1 1 "killqst" "dellib" "freelib")
489 498 (opengame nil 0 0)
490 499 (savegame nil 0 0)
491 500 ;; Real time
492 501 (wait nil 1 1)
493 502 (msecscount t 0 0)
494 503 (settimer nil 1 1))
495 504
496 505 ;;; Expression
497 506
498 507 (p:defrule expression or-expr)
499 508
500 509 (p:defrule or-expr (and and-expr (* (and spaces? or-op spaces? and-expr)))
501 510 (:function do-binop))
502 511
503 512 (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr)))
504 513 (:function do-binop))
505 514
506 (p:defrule eq-expr (and cat-expr (* (and spaces? (or "<>" "<=" ">=" "=<" "=>"
507 #\= #\< #\> #\!)
515 (p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>"
516 "=" "<" ">" "!")
508 517 spaces? cat-expr)))
509 518 (:function do-binop))
510 519
511 (p:defrule cat-expr (and sum-expr (* (and spaces? #\& spaces? (p:! expr-stopper) sum-expr)))
512 (:lambda (list)
513 (do-binop (list (first list) (mapcar (lambda (l)
514 (remove-nth l 3))
515 (second list))))))
516
517 520 (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr)))
518 521 (:function do-binop))
519 522
520 523 (p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr)))
521 524 (:function do-binop))
522 525
523 526 (p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr)))
524 527 (:function do-binop))
525 528
526 529 (p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr)
527 530 (:lambda (list)
528 531 (let ((expr (remove-nil list)))
529 532 (if (= 1 (length expr))
530 533 (first expr)
531 534 (intern-first expr)))))
532 535
533 536 (p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr) spaces?)
534 537 (:function first))
535 538
536 539 (p:defrule paren-expr (and #\( spaces? expression spaces? #\))
537 540 (:function third))
538 541
539 542 (p:defrule or-op (p:~ "or")
540 543 (:constant "or"))
541 544
542 545 (p:defrule and-op (p:~ "and")
543 546 (:constant "and"))
544 547
545 548 ;;; Variables
546 549
547 550 (p:defrule variable (and identifier (p:? array-index))
548 551 (:destructure (id idx)
549 552 (list 'var id (or idx 0))))
550 553
551 554 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
552 555 (:lambda (list)
553 556 (or (third list) :end)))
554 557
555 (p:defrule assignment (or kw-assignment plain-assignment)
558 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
556 559 (:destructure (var eq expr)
557 560 (declare (ignore eq))
558 561 (list 'set var expr)))
559 562
563 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? (or op-assignment plain-assignment))
564 (:function third))
565
566 (p:defrule op-assignment (and variable spaces? (or "+" "-" "*" "/") #\= spaces? expression)
567 (:destructure (var ws1 op eq ws2 expr)
568 (declare (ignore ws1 ws2))
569 (list var eq (intern-first (list op var expr)))))
570
560 571 (p:defrule plain-assignment (and variable spaces? #\= spaces? expression)
561 572 (:function remove-nil))
562 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? plain-assignment)
563 (:function third))
564 573
565 574 ;;; Non-string literals
566 575
567 576 (p:defrule literal (or qsp-string brace-string number))
568 577
569 578 (p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
570 579 (:lambda (list)
571 580 (parse-integer (p:text list))))
General Comments 0
You need to be logged in to leave comments. Login now