Встретился с необходимостью проверить, являются ли данные рабочим кодом на lisp.
Задача. Функция получает на вход строку. Нужно проверить,
является ли эти данные работающим/eval'ируемым в данном контексте кодом lisp, не eval'я его.
Не нашёл такой встроенной функции. Работаю в eclips, компилятор - sbcl.
Проверяемый код без макросов и смены пакета.
Не хочется писать компилятор, когда есть уже, или же "подпихивать" в другой процесс-компилятор.
Пробовал просто обрабатывать исключение eval... Пробовал пробегать весь пакет и сравнивать со словами в строке. Но так не нравится.
Если есть eval, compile, eval-when и другие функции, то должна же быть проверка на "работоспособность"!!
Помогите, пожалуйста!!!! и прошу прощения, если что неправильно написал, я ещё новичок...
Без макросов - всмысле без reader-макросов, или что, совсем из одних вызовов функций и специальных операторов?
Ну, ты можешь вызывать READ.READ либо вернет лисповый объект, либо вызовет исключение.
Код на лиспе это в принципе абсолютно любой лисповый объект, а его вычисление зависит от состояния лисп-системы.
В общем случае, проверить корректно ли семантически полученное от READ ast можно только вычислив его.
Оно может стать некорректным прямо в процессе вычисления, потому что.
Компилятором можно проверить так:
(lambda (form)
(null (nth-value 2 (compile nil `(lambda () ,form)))))Хотя это не проверка на
"работоспособность", конечно.Спасибо за ответы!!! Покажу на примере. Строка например будет (setf string1 "(+ 2 3)") мне нужна функция (lisp-p), которая сработает с такой строкой так (lisp-p string1)=>T; если же функция или аргументы будут неизвестными в текущем контексте: (setf string2 "(gkjj bbm 8)") , то (lisp-p string2)=> NIL; Вот "первое приближение" - здесь я просто смотрю есть ли скобки в строке и пробегаю по контексту, сравнивая "слова" в строке и символы. Если все слова в строке присутствуют и скобки есть - то строка и вправду код лиспа. Для чего это нужно. Чтобы программа могла самостоятельно отличить вводится код лиспа или просто строка. Хотел доделать эту функцию с учётом вложеных скобок, макросов, квазицитирования и тд. Но перед этим решил спросить у более опытных - может такое уже есть.
(defun lisp-p (stringa)
(setf wrds (to-words stringa " ():,'\/"))
(setf iter 0)
(with-package-iterator (next-symbol *package*
:internal :external :inherited)
(loop
(multiple-value-bind (more? symbol) (next-symbol)
(if more?
(dolist (wrd wrds)
(if (not (position #\Newline wrd))
(if (equal symbol (read-from-string wrd))
(incf iter) )) )
(return)))))
(if (and (position #\( stringa) (position #\)stringa))
(if (and (< (position #\( stringa) (position #\)stringa))
(> iter 0)) t nil) nil))
Есть, кстати, готовый парсер грамматики s-выражений. Очень удобный на мой взгляд.
https://github.com/nikodemus/esrap/blob/master/example-sexp.lisphttps://github.com/nikodemus/esrapПосле составления ast дерева, вам необходимо самостоятельно проверить его корректность. Если у вас "простой лисп", то вроде как не сложно.
Спасибо большое! Да, как раз "простой"!