diff --git a/.hgignore b/.hgignore new file mode 100644 --- /dev/null +++ b/.hgignore @@ -0,0 +1,2 @@ +.*~ +.qlot diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ + +all: diagrams.png $(BIN) + +$(BIN): src/*.lisp src/*.ps + buildapp.sbcl + +install-deps: + sbcl --load install-deps.lisp + +update-deps: + sbcl --load update-deps.lisp + +diagrams.png: diagrams.dot + dot $< -T png -o $@ + +clean: + rm sugar-qsp diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -1,2 +1,44 @@ +(Russian readme below) # sugar-qsp Compiler for QSP games which creates monolithic HTML pages. + +## Usage + +There are three mastery levels + +1. Just build me the game: + +`sugar-qsp game.txt` +And it will create the game in game.html + +2. I know what I'm doing: +`sugar-qsp game.txt -o game.html --body body.html --js jquery.js my-js-library.js --css styles/*.css` +All options are self-explanatory. The result is a monolithic html specified +with the `-o` option. Default `body.html` (used by the first mastery level) can +be found in `extas` directory. + +3. I'm a frontend developer! +`sugar-qsp game.txt -c -o game.js` +It just builds the game script into a js you can put on your website. To run +the game execute `SugarQSP.start()` + +# sugar-qsp +Компилятор для игр на QSP создающий монолитные страницы на HTML. + +## Инструкции + +Есть три уровня мастерства. + +1. Просто собери мне игру: +`sugar-qsp game.txt` +Создаст игру в game.html + +2. Я знаю что делаю: +`sugar-qsp game.txt -o game.html --body body.html --js jquery.js my-js-library.js --css styles/*.css` +Если вы знаете что делаете, то для вас смысл опций очевиден. `body.html` +по-умолчанию лежит в каталоге `extras`. + +3. Я - фронтендер! +`sugar-qsp game.txt -c -o game.js` +Просто соберёт игру в Javascript файл который вы можете разместить на своём +сайте как вам угодно. Для запуска игры вызовите `SugarQSP.start()`. diff --git a/TODO b/TODO new file mode 100644 --- /dev/null +++ b/TODO @@ -0,0 +1,9 @@ + +* API +* Sample +* html +* bundle it all +* Qlot +* make a binary + +* Finish intrinsics and api \ No newline at end of file diff --git a/diagrams.dot b/diagrams.dot new file mode 100644 --- /dev/null +++ b/diagrams.dot @@ -0,0 +1,18 @@ + +digraph diagrams { + rankdir = LR + subgraph cluster_code { + label = "Code Transformations" + QSP -> intermediate [label="parser.lisp (esrap)"] + intermediate -> Parenscript [label="ps-macros.lisp"] + Parenscript -> Javascript [label="main.lisp"] + } + subgraph cluster_js { + label = "Javascript modules call hierarchy" + user -> "ps-macros" + user -> intrinsics + "ps-macros" -> intrinsics + "ps-macros" -> api + intrinsics -> api + } +} diff --git a/diagrams.png b/diagrams.png new file mode 100644 index 0000000000000000000000000000000000000000..5bdab3edf167918f97c629e102afe53e8bff33f8 GIT binary patch literal 38842 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 diff --git a/examples/10dynamic.txt b/examples/10dynamic.txt new file mode 100644 --- /dev/null +++ b/examples/10dynamic.txt @@ -0,0 +1,22 @@ + +# dynamic +DYNAMIC {$a=0} +DYNAMIC {if $a="string":'text!'} +DYNAMIC { + $args[0] + addobj $args[1] +},'Текст','Вилка' + +DYNEVAL({result = 3+4}) +PL DYNEVAL({$result = mid("abcd",2,1)+"qwerty"}) +PL DYNEVAL({$test + $args[0]}, val($test)) +проход=DYNEVAL({result = ($args[0] <> 'текст')}, 'строка') + +$code = { + *pl "<<$args[0]>>" + *pl $args[0] +} + +DYNAMIC $code,'asdfg' +! будет выведено две строки 'asdfg' +- diff --git a/examples/11main.txt b/examples/11main.txt new file mode 100644 --- /dev/null +++ b/examples/11main.txt @@ -0,0 +1,8 @@ + +# main +*P '1' +$txt = $MAINTXT +*PL '23' +*NL '456' +'78' +- diff --git a/examples/12aux.txt b/examples/12aux.txt new file mode 100644 --- /dev/null +++ b/examples/12aux.txt @@ -0,0 +1,7 @@ + +# aux +P '1' +$txt = $STATTXT +PL '23' +NL '456' +- diff --git a/examples/13diag.txt b/examples/13diag.txt new file mode 100644 --- /dev/null +++ b/examples/13diag.txt @@ -0,0 +1,18 @@ + +# diag +! простой вывод сообщения. +MSG 'Много спелых груш' +! получим окно с сообщением 'Много спелых груш' + +! Пример сообщения в действии ACT. +ACT 'Поесть груш': + MSG 'Ммм груши очень вкусные' +END +! Получим вывод сообщения при клике по действию "Поесть груш" + +!Пример с условием. +IF $hlebgotov = 1: +MSG 'Похоже хлеб уже готов' +END +! Получаем вывод сообщения когда условие $hlebgotov = 1 +- diff --git a/examples/14act.txt b/examples/14act.txt new file mode 100644 --- /dev/null +++ b/examples/14act.txt @@ -0,0 +1,8 @@ + +# act +act 'test', 'img': + act 'test2': + 'omg' + end +end +- diff --git a/examples/15objs.txt b/examples/15objs.txt new file mode 100644 --- /dev/null +++ b/examples/15objs.txt @@ -0,0 +1,21 @@ + +# objs +OBJECTS['деньги'] = 12 +OBJECTS['патроны'] = 137 + +'Количество: <>' + +!Первый предмет в списке +GETOBJ(1) + +!Последний предмет в списке +GETOBJ(COUNTOBJ) + +i = 1 +:loop +IF i <= COUNTOBJ: + OBJECTS[$GETOBJ(i)] = OBJECTS[$GETOBJ(i)] + 1 + i = i + 1 + JUMP 'loop' +END +- diff --git a/examples/16menu.txt b/examples/16menu.txt new file mode 100644 --- /dev/null +++ b/examples/16menu.txt @@ -0,0 +1,13 @@ + +# menu +! нет иконки +$usr_menu[0] = 'Взять предмет:take_item' +! иконка задана gif-файлом +$usr_menu[1] = 'Положить предмет:put_item:images/put_item.gif' +! иконка задана значением $icon_file +$usr_menu[2] = 'Осмотреть предмет:look_item:<<$icon_file>>' +! пункт меню задан 3-мя переменными +$usr_menu[3] = '<<$name>>:<<$loc>>:<<$file>>' + +menu 'usr_menu' &! покажет меню из 4-х пунктов +- diff --git a/examples/17sound.txt b/examples/17sound.txt new file mode 100644 --- /dev/null +++ b/examples/17sound.txt @@ -0,0 +1,15 @@ + +# sound +!Громкость 100% +PLAY 'sound/music.mp3' +!Громкость 50% +PLAY 'sound/music.mp3',50 +!Громкость 0% (без звука) +PLAY 'sound/music.mp3',0 + +!Проигрывание файла по адресу из переменной $file +! с расширением 'mid' +! и громкостью volume +PLAY '<<$file>>.mid',volume +PLAY $file,volume &! аналогично +- diff --git a/examples/18img.txt b/examples/18img.txt new file mode 100644 --- /dev/null +++ b/examples/18img.txt @@ -0,0 +1,14 @@ + +# img +$BACKIMAGE = 'content/back.png' + +VIEW 'content/monster.png' + +! Включаем режим HTML. Если во всей игре используется HTML, +! то достаточно включить его на самой первой локации. +USEHTML = 1 +! Выводим картинку в основное описание +'' +! Выводим картинку в доп. описание +PL '' +- diff --git a/examples/19input.txt b/examples/19input.txt new file mode 100644 --- /dev/null +++ b/examples/19input.txt @@ -0,0 +1,20 @@ + +# input +$text = $USER_TEXT +CMDCLEAR +SHOWINPUT 0 + +$name = INPUT('Как звать тебя, герой?') + +! Вопрос с одним правильным ответом. +if input ('Что приходит после тьмы?') = 'свет': + msg 'Все верно.' + else + msg 'Ответ не верный.' +end + +! Пример реализации вопроса с несколькими вариантами ответа из которых любой будет правильным. +$answer = TRIM(LCASE(input('Ответить'))) +if INSTR($answer, 'красный') OR INSTR($answer, 'желтый') OR INSTR($answer, 'зеленый'): gt 'win' +! Введя красный или зеленый ил желтый произойдет переход на локацию 'win' +- diff --git a/examples/1loc.txt b/examples/1loc.txt new file mode 100644 --- /dev/null +++ b/examples/1loc.txt @@ -0,0 +1,9 @@ + +# loc +GT 'локация' +GT 'локация',1,'данные' +- + +# локация + +- diff --git a/examples/20time.txt b/examples/20time.txt new file mode 100644 --- /dev/null +++ b/examples/20time.txt @@ -0,0 +1,44 @@ + +# time +! устанавливает период выполнения кода +! на локации-счётчике в 100 миллисекунд +SETTIMER 100 + +settimer 20 +if стихотворение=0: + if время_первая_строка=0: + время_первая_строка=msecscount+1500 + end + if msecscount>=время_первая_строка: + *pl 'Веленью совести, о Муза, будь послушна!' + стихотворение=1 + end +end +if стихотворение=1: + if время_вторая_строка=0: + время_вторая_строка=msecscount+1500 + end + if msecscount>=время_вторая_строка: + *pl 'Обиды не страшась, не требуя венца,' + стихотворение=2 + end +end +if стихотворение=2: + if время_третья_строка=0: + время_третья_строка=msecscount+1500 + end + if msecscount>=время_третья_строка: + *pl 'Хвалу и клевету приемли равнодушно' + стихотворение=3 + end +end +if стихотворение=3: + if время_четвёртая_строка=0: + время_четвёртая_строка=msecscount+1500 + end + if msecscount>=время_четвёртая_строка: + *pl 'И не оспаривай глупца.' + стихотворение=4 + end +end +- diff --git a/examples/2var.txt b/examples/2var.txt new file mode 100644 --- /dev/null +++ b/examples/2var.txt @@ -0,0 +1,7 @@ + +# var +var1 = 42 +SET var2 = 42 +LET var3 = 42 +KILLVAR 'var1' +- diff --git a/examples/3expr.txt b/examples/3expr.txt new file mode 100644 --- /dev/null +++ b/examples/3expr.txt @@ -0,0 +1,16 @@ + +# expr +x=5 +y=6 +tmp=(x ! y) OR (x <> y) +tmp=x OR y +tmp=x AND y +tmp=y MOD x +tmp=OBJ 'стул' +tmp=LOC 'дом' +tmp=res = x*y + y*-x/2 +tmp=res = NO x = y + +tmp=15*5/2 +tmp=15/2*5 +- diff --git a/examples/4code.txt b/examples/4code.txt new file mode 100644 --- /dev/null +++ b/examples/4code.txt @@ -0,0 +1,56 @@ + +# code +яблоко = 1 +груша = 1 + +*pl 'Яблок' + яблоко +*pl 'Груш' + груша + +'яблоко' +!При нажатии на ссылку выполнится код: +яблоко += 1 +GT $CURLOC + + !Однострочный комментарий + яблоки = 0 +!'Многострочный +комментарий' +яблоки = 1 + сыр = 5 & ! А здесь"комментарий начинается + в той же строке, но" заканчивается 'сильно + позже'. Во всём виноваты {кавычки и скобки + }Кстати: + яблоки=0 + !'Комментарии рекомендуется писать всё-таки +в отдельных строках, а не как с "сыром"' + +!'Общий вид вызова оператора + имя_оператора аргумент1, аргумент2, ... +или + имя_оператора (аргумент1, аргумент2, ...) +' +!Примеры вызовов операторов: +ADDOBJ 'ключ','pics/key.png' +ADDOBJ ('ключ','pics/key.png') +PL ('текст') +CLEAR() + +!Примеры вызовов функций: +X = MAX(1, 2, 4) +A = RAND(4) +B = COUNTOBJ +PL STR(43) +PL $STR(43) +!Последние два выражения эквивалентны + +RAND(1,4) &! вернёт случайное значение от 1 до 4 +RAND(4,1) &! вернёт случайное значение от 1 до 4 +RAND(1000) &! вернёт случайное значение от 0(1) до 1000 +RAND 1000 &! вернёт случайное значение от 0(1) до 1000 + +MAX(1,2,5,2,0) &! вернёт 5 +MAX(a,b,c) &! вернёт максимальное из значений переменных a,b,c +MAX('aa','ab','zz') &! вернёт 'zz' +MAX('a') &! вернёт максимальное из значений элементов массива "a" +MAX('$b') &! вернёт максимальное из значений элементов массива "$b" +- diff --git a/examples/5arrays.txt b/examples/5arrays.txt new file mode 100644 --- /dev/null +++ b/examples/5arrays.txt @@ -0,0 +1,25 @@ + +# arrays +$яблоки[0]='антоновка' +$яблоки[1]='белый налив' +$яблоки[2]='астраханское' +$яблоки[3]='ранетка' +$яблоки[4]='симиренко' + +сорт_яблока[0] = 1 +сорт_яблока[1] = 2 +сорт_яблока[2] = 4 + +*pl $яблоки[сорт_яблока[номер_яблока]] + +$любимый_сорт['иван'] = $яблоки[2] +любимое_число['Алексей'] = 5 +$item_loc['палка'] = 'лес' + +$objs[] = 'Напильник' &! Если массив был пустой, то +$objs[] = 'Топор' &! [0] = 'Напильник', +$objs[] = 'Доска' &! [1] = 'Топор', [2] = 'Доска' + +$a = $objs[] &! 'Доска' из примера выше +a = сорт_яблока[] &! 4 из примера выше +- diff --git a/examples/6str.txt b/examples/6str.txt new file mode 100644 --- /dev/null +++ b/examples/6str.txt @@ -0,0 +1,19 @@ + +# str +*PL 'Byte Soft''s "QSP"' +*PL "Byte Soft's ""QSP""" + +'Данный текст +будет расположен на +нескольких строках' + +$a='И этот +текст +также' + +a=2 & act 'Многострочное +название':gt 'next' & GoTo 'next' + +$res = ('x=' & x & ' y=' & y) +$res = 'x=' & x +- diff --git a/examples/7if.txt b/examples/7if.txt new file mode 100644 --- /dev/null +++ b/examples/7if.txt @@ -0,0 +1,56 @@ + + +# if-elseif +IF a=1: + !операторы +ELSEIF a=2: + !операторы +ELSEIF a=3: + !операторы +END + +- + +# if-iif +!Модуль числа +abs_x = IIF(x > 0, x, -x) + +!А следующая конструкция вызовет ошибку деления на ноль: +x = 0 +y = IIF(x = 0, 0, 1/x) +- + +# if-inline +if ((a+b)/c)=45+54 or (b<5 or c>45) and no obj 'лопата' and $f=$vvv+'RRRRR': p 'OK' & goto 'Next' +if был_здесь[$curloc]: exit +if a<3: jump 'sss' +if $имя = '': msg 'Введите имя!' & jump 'ввод' +if a+b=2:c=30 & gt 'next' else c=10 & d=11 +- + +# if-lines +if a+b<3 or y=8: + p 'A+B<3 или Y=8' + nl + if j=88: nl & p 'NEXT' + if $h='ooo': + p 'loo' & jump 'lll' + end +end + +if a=0: + 'abc1234' + if b=0: '0' else '1' + if j=88:nl & p 'NEXT' + if $h='ooo': + p 'loo' & jump 'lll' + else + p 'sample text' + v=8 + end + '1234' +else + '01234' + g=78 +end +- diff --git a/examples/8sub.txt b/examples/8sub.txt new file mode 100644 --- /dev/null +++ b/examples/8sub.txt @@ -0,0 +1,18 @@ + +# sub +GS 'переход', 'локация' +GS 'ход' +GS $loc,1 +GS 'ход',$var,2,'данные' +яблоки = FUNC('функция') +PL FUNC($name, 1) * 78 +MSG "text" + FUNC($name, "строка", 2) +if args[0] = 0: exit +- + +#переход +*PL $ARGS[0] &! На экран выведется 'локация' +ACT 'Перейти': + GT $ARGS[0] &! Работать не будет, т.к. массив ARGS пуст +END +- diff --git a/examples/9loops.txt b/examples/9loops.txt new file mode 100644 --- /dev/null +++ b/examples/9loops.txt @@ -0,0 +1,27 @@ + +# loops +jump 'КонеЦ' +p 'Это сообщение не будет выведено' +:конец +p 'А это сообщение пользователь увидит' + +s=0 +:loop +if s<9: + s=s+1 + pl s + jump 'loop' +end +p 'Всё!' + +:loop +if yc6LR&2kSnauIt`@HXa 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 diff --git a/src/parser.lisp b/src/parser.lisp new file mode 100644 --- /dev/null +++ b/src/parser.lisp @@ -0,0 +1,568 @@ + +(in-package sugar-qsp) + +;;;; Parses TXT source to an intermediate representation + +;;; Utility + +(defun remove-nth (list nth) + (append (subseq list 0 nth) + (subseq list (1+ nth)))) + +(defun not-quote (char) + (not (eql #\' char))) + + +(defun not-doublequote (char) + (not (eql #\" char))) + +(defun not-brace (char) + (not (eql #\} char))) + +(defun not-integer (string) + (when (find-if-not #'digit-char-p string) + t)) + +(defun not-newline (char) + (not (eql #\newline char))) + +(defun id-any-char (char) + (and + (not (digit-char-p char)) + (not (eql #\newline char)) + (not (find char " !:&=<>+-*/,'\"()[]{}")))) + +(defun intern-first (list) + (list* (intern (string-upcase (first list))) + (rest list))) + +(defun remove-nil (list) + (remove nil list)) + +(defun binop-rest (list) + (destructuring-bind (ws1 operator ws2 operand2) + list + (declare (ignore ws1 ws2)) + (list (intern (string-upcase operator)) operand2))) + +(defun do-binop% (left-op other-ops) + (if (null other-ops) + left-op + (destructuring-bind ((operator right-op) &rest rest-ops) + other-ops + (if (eq (first left-op) + operator) + (do-binop% (append left-op (list right-op)) rest-ops) + (do-binop% (list operator left-op right-op) rest-ops))))) + +(defun do-binop (list) + (destructuring-bind (left-op rest-ops) + list + (do-binop% left-op + (mapcar #'binop-rest rest-ops)))) + +(p:defrule line-continuation (and #\_ #\newline) + (:constant nil)) + +(p:defrule text-spaces (+ (or #\space #\tab line-continuation)) + (:text t)) + +(p:defrule spaces (+ (or #\space #\tab line-continuation)) + (:constant nil)) + +(p:defrule spaces? (* (or #\space #\tab line-continuation)) + (:constant nil)) + +(p:defrule colon #\: + (:constant nil)) + +(p:defrule alphanumeric (alphanumericp character)) + +(p:defrule not-newline (not-newline character)) + +(p:defrule squote-esc "''" + (:lambda (list) + (p:text (elt list 0)))) + +(p:defrule dquote-esc "\"\"" + (:lambda (list) + (p:text (elt list 0)))) + +(p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:"))) + (or squote-esc (not-quote character)))) + (:lambda (list) + (p:text (mapcar #'second list)))) + +(p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:"))) + (or dquote-esc (not-doublequote character)))) + (:lambda (list) + (p:text (mapcar #'second list)))) + +;;; Identifiers + +;; From the official docs +(defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize $backimage bcolor 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 usehtml $usercom user_text usrtxt val view wait xgoto xgt)) + +(defun qsp-keyword-p (id) + (member (intern (string-upcase id)) *keywords*)) + +(defun not-qsp-keyword-p (id) + (not (member (intern (string-upcase id)) *keywords*))) + +(p:defrule qsp-keyword (qsp-keyword-p identifier-raw)) + +(p:defrule id-first (id-any-char character)) +(p:defrule id-next (or (id-any-char character) + (digit-char-p character))) +(p:defrule identifier-raw (and id-first (* id-next)) + (:lambda (list) + (let ((id (p:text list))) + (when (member id *keywords*) + (error "~A is a keyword" id)) + (intern (string-upcase id))))) + +(p:defrule identifier (not-qsp-keyword-p identifier-raw)) + +;;; Strings + +(p:defrule qsp-string (or normal-string brace-string)) + +(p:defrule normal-string (or sstring dstring) + (:lambda (str) + (list* 'str (or str (list ""))))) + +(p:defrule sstring (and #\' (* (or string-interpol + sstring-exec + sstring-chars)) + #\') + (:function second)) + +(p:defrule dstring (and #\" (* (or string-interpol + dstring-exec + dstring-chars)) + #\") + (:function second)) + +(p:defrule string-interpol (and "<<" expression ">>") + (:function second)) + +(p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character))) + (:text t)) + +(p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character))) + (:text t)) + +(p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\") + (:lambda (list) + (list* 'exec (p:parse 'exec-body (second list))))) + +(p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\') + (:lambda (list) + (list* 'exec (p:parse 'exec-body (second list))))) + +(p:defrule brace-string (and #\{ before-statement block-body #\}) + (:lambda (list) + (list* 'qspblock (third list)))) + +;;; Location + +(p:defrule sugar-qsp-grammar (and (* (or spaces #\newline)) + (* location)) + (:function second)) + +(p:defrule location (and location-header block-body location-end) + (:destructure (header body end) + (declare (ignore end)) + `(location (,header) ,@body))) + +(p:defrule location-header (and #\# + (+ not-newline) + (and #\newline spaces? before-statement)) + (:destructure (spaces1 name spaces2) + (declare (ignore spaces1 spaces2)) + (string-upcase (string-trim " " (p:text name))))) + +(p:defrule location-end (and #\- #\newline before-statement) + (:constant nil)) + +;;; Block body + +(p:defrule newline-block-body (and #\newline spaces? block-body) + (:function third)) + +(p:defrule block-body (* statement) + (:function remove-nil)) + +;; Just for " "<=" ">=" "=<" "=>" + #\= #\< #\> #\!) + spaces? cat-expr))) + (:function do-binop)) + +(p:defrule cat-expr (and sum-expr (* (and spaces? #\& spaces? (p:! expr-stopper) sum-expr))) + (:lambda (list) + (do-binop (list (first list) (mapcar (lambda (l) + (remove-nth l 3)) + (second list)))))) + +(p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr))) + (:function do-binop)) + +(p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr))) + (:function do-binop)) + +(p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr))) + (:function do-binop)) + +(p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr) + (:lambda (list) + (let ((expr (remove-nil list))) + (if (= 1 (length expr)) + (first expr) + (intern-first expr))))) + +(p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr exists-expr) spaces?) + (:function first)) + +(p:defrule paren-expr (and #\( spaces? expression spaces? #\)) + (:function third)) + +(p:defrule or-op (p:~ "or") + (:constant "or")) + +(p:defrule and-op (p:~ "and") + (:constant "and")) + +;;; Variables + +(p:defrule variable (and identifier (p:? array-index)) + (:destructure (id idx) + (list 'var id (or idx 0)))) + +(p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\]) + (:lambda (list) + (or (third list) :end))) + +(p:defrule assignment (or kw-assignment plain-assignment) + (:destructure (var eq expr) + (declare (ignore eq)) + (list 'set var expr))) + +(p:defrule plain-assignment (and variable spaces? #\= spaces? expression) + (:function remove-nil)) +(p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? plain-assignment) + (:function third)) + +;;; Non-string literals + +(p:defrule literal (or qsp-string brace-string number)) + +(p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)) + (:lambda (list) + (parse-integer (p:text list)))) diff --git a/src/ps-macros.fasl b/src/ps-macros.fasl new file mode 100644 index 0000000000000000000000000000000000000000..43050478c4b539791cdd5cdcac998a65e5092814 GIT binary patch literal 79458 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 Q (op1 op2) + `(not (equal ,op1 ,op2))) + +(ps:defpsmacro ! (op1 op2) + `(not (equal ,op1 ,op2))) + +;;; 4code + +(ps:defpsmacro exec (&body body) + (format nil "javascript: ~{~A~^~%~}" (mapcar #'ps:ps* body))) + +;;; 5arrays + +;;; 6str + +(ps:defpsmacro & (&rest args) + `(ps:chain "" (concat ,@args))) + +;;; 7if + +(ps:defpsmacro qspcond (&rest clauses) + `(cond ,@(loop :for clause :in clauses + :collect (list (first clause) + `(tagbody ,@(rest clause)))))) + +;;; 8sub + +;;; 9loops +;;; Yep, that's a huge kludge since Javascript doesn't support arbitrary labels + +(ps:defpsmacro jump (target) + `(return-from ,(intern (string-upcase (second target))) + (funcall (ps:getprop __labels ,target)))) + +(ps:defpsmacro tagbody (&body body) + (let ((funcs (list nil :__nil))) + (dolist (form body) + (cond ((keywordp form) + (setf (first funcs) (reverse (first funcs))) + (push form funcs) + (push nil funcs)) + (t + (push form (first funcs))))) + (setf (first funcs) (reverse (first funcs))) + (setf funcs (reverse funcs)) + (if (= 2 (length funcs)) + `(progn + ,@body) + `(progn + (setf ,@(loop :for f :on funcs :by #'cddr + :append (list `(ps:@ __labels ,(first f)) + `(block ,(intern (string-upcase (string (first f)))) + ,@(second f) + ,@(when (third f) + `((funcall + (ps:getprop __labels ,(third f))))))))) + (jump (str "__nil")))))) + +(ps:defpsmacro exit () + `(throw :exit)) + +;;; 10dynamic + +(ps:defpsmacro qspblock (&body body) + `(lambda () + (defvar __labels) + ,@body + (values))) + +;;; 11main + +(ps:defpsmacro act (name &body body) + `(api-call add-act ,name (lambda () + (big-block + (tagbody + ,@body))))) + +;;; 12aux + +;;; 13diag + +;;; 14act + +;;; 15objs + +;;; 16menu + +;;; 17sound + +;;; 18img + +;;; 19input + +;;; 20time diff --git a/src/writer.lisp b/src/writer.lisp new file mode 100644 --- /dev/null +++ b/src/writer.lisp @@ -0,0 +1,9 @@ + +(in-package sugar-qsp) + +;;; 1. Generates parenscript source to write to js +;;; 2. Collects everything into complete file, leaving a neatly marked +;;; place to customize page layout and styles. + +(defun make-javascript (locations) + (mapcar #'ps:ps* locations)) diff --git a/sugar-qsp.asd b/sugar-qsp.asd new file mode 100644 --- /dev/null +++ b/sugar-qsp.asd @@ -0,0 +1,10 @@ + +(defsystem sugar-qsp + :description "QSP compiler to monolithic HTML page" + :depends-on (:alexandria :esrap :parenscript :cl-uglify-js) + :pathname "src/" + :serial t + :components ((:file "package") + (:file "main") + (:file "ps-macros") + (:file "parser"))) diff --git a/update-deps.lisp b/update-deps.lisp new file mode 100644 --- /dev/null +++ b/update-deps.lisp @@ -0,0 +1,3 @@ +(ql:quickload :qlot) +(asdf:load-system :qlot/cli) +(qlot/cli:update)