LINUX.ORG.RU

[noob] Lisp и DSL - научите!

 


0

0

Придумал такую задачу - написать простенькую систему учета оргтехники, чисто для того, чтобы понять, как строить DSL.

Далее будет поток сознания, знающих людей попрошу поправлять по ходу.

Язык имеет следующий вид:

device videocard labeled "Videocard"	{
       required hex vendor labeled "Vendor"
       required hex device labeled "Device"
       optional date released labeled "Release Date"
       required string inventory-id labeled "Inventory #"
       required set status labeled "Status" value: ordered, in-store, in-repair, stopped-using, wrote-off
}

На основе него должны генерироваться таблицы для sql и формы для gui.

Нужно представить код dsl в пригодном для обработки виде:

(device videocard "Videocard"
  ((vendor required hex "Vendor")
   (device required hex "Device")
   (released optional date "Release Date")
   (inventory-id required string "Inventory #")
   (status required set "Status" (ordered, in-store, in-repair, stopped-using, wrote-off))))

И вот уже на основе этого строятся макросы, функции и классы - здесь вроде все понятно. У меня затык возник на стадии парсинга из исходного представления в s-выражения. Я просто не могу выразить алгоритм на лиспе, ибо только учусь.

Ответ на: комментарий от dmitry_vk

Можно посмотреть на antlr. Не знаю, правда, умеет ли она lisp.

Ian ★★
()
Ответ на: комментарий от dmitry_vk

Можно посмотреть на antlr. Не знаю, правда, умеет ли она lisp.

Ian ★★
()
Ответ на: комментарий от dmitry_vk

Вся соль в том, что хочу разобраться, как сделать это самому.

pyani_master
() автор топика
Ответ на: комментарий от pyani_master

На лиспе легко сделать DSL:) Если DSL построен на s-expr'ах, то пишется совсем просто. Так как есть макросы, с помощью которых легко преобразовывать исходный код.

Если не на s-expr'ах, то нужна грамматика, будь это трижды лисп или трижды джава. Если хочется, то парсер можно встроить в лисповский парсер, чтобы DSL можно было использовать прямо в исходном коде рядом с лисповским кодом (правда, у текстового редактора будут проблемы с подсветкой и редактированием такого кода).

Для парсеров есть свои DSL (в тех же cl-yacc или fucc). Использовать их проще, так как не нужно отдельных файлов с грамматикой, отдельных шагов компиляции. В этом тоже преимущество лиспа.

dmitry_vk ★★★
()
Ответ на: комментарий от pyani_master

> Лисперы постоянно говорят, что на Лиспе легко делать DSL

Анонимные лисперы это говорили, пока их не зобанели %)

tailgunner ★★★★★
()
Ответ на: комментарий от dmitry_vk

> Для парсеров есть свои DSL (в тех же cl-yacc или fucc). Использовать их проще, так как не нужно отдельных файлов с грамматикой, отдельных шагов компиляции. В этом тоже преимущество лиспа.

К Лиспу это не имеет никакого отношения. В Питоне есть SPARK, TPG и прочие, которые тоже не требуют отдельных файлов с грамматикой и явной компиляции. Другое дело, что особым преимуществом это не является.

tailgunner ★★★★★
()

>И вот уже на основе этого строятся макросы, функции и классы - здесь вроде все понятно.

Напиши пока эти самые макросы, функции и классы (а они тебе правда нужны?). Отладь всё это.

Кстати, при отладке и тестировании, использование языка в S-exp даст тебе преимущества (можно и пробные куски кода сгенерировать, причём прямо в REPL:)).

>У меня затык возник на стадии парсинга из исходного представления в s-выражения.

Парсер целевой грамматики в S-exp я делаю в последнюю очередь, т.к. это почти механическая работа: описал грамматику, cl-yacc в зубы и вперёд.

Sectoid ★★★★★
()
Ответ на: комментарий от tailgunner

>К Лиспу это не имеет никакого отношения.

Ну так человек это и сказал (цитирую):

"Если не на s-expr'ах, то нужна грамматика, будь это трижды лисп или трижды джава."

К теме. Я вот присоединяюсь к совету начать с записи целевых s-expr, написать макросы, а уж потом уже решать вопрос с преобразованием. Я примерно так и сделал. Исходный файл у меня описан в XML. Я сначала записал, как я хочу это видеть в s-выражениях и написал макросы, а потом уже взял простой парсер XML (xmls) и сгенерировал необходимые мне s-выражения.

Zubok ★★★★★
()

Возникли сложности. Язык изменил, приведя к следующему виду:
(defparameter *example-language-line* '(device videocard "Videocard"
					((vendor-id required int "Vendor" (units nil) (value nil))
					 (device-id required int "Device" (units nil) (value nil))
					 (released optional date "Release Date" (units nil) (value nil))
					 (inventory-id required string "Inventory #" (units nil) (value nil))
					 (status required (enum ordered in-store in-repair stopped-using wrote-off) "Status" (units nil) (value ordered)))))

Рожденная мною макра выглядит так:

(defmacro device (name label standalone? &body fields)
  `(progn
     (defclass ,name ()
       ((label
	 :type string
	 :initform ,label)
	(standalone?
	 :type boolean
	 :initform ,standalone?)
	,@(loop for (slot nil nil nil) in fields
	     collect slot)))))

Вопросы такие:
1. В какую структуру лучше запихнуть строки типа:
(vendor-id required int "Vendor" (units nil) (value nil)),
учитывая, что на основе первого элемента будут генерить слоты класса в макре device?
2. Как собственно сгенерить слоты учитывая, что мне понадобятся такие штуки, как типы данных, initarg, initform и accessor?
3. Где найти справочник по функциям/макрам Лиспа?

pyani_master
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.