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