Прежде всего, вы никогда не должны читать код clojure непосредственно из ненадежных источников данных. Вместо этого вы должны использовать EDN или другой формат сериализации.
С учетом того, что с Clojure 1.5 существует безопасный способ чтения строк без их уклонения. Перед использованием строки чтения необходимо привязать read-eval var к false. В Clojure 1.4 и ранее это потенциально приводило к побочным эффектам, вызванным вызовом конструкторов java. С тех пор эти проблемы были исправлены.
Вот несколько примеров кода:
(defn read-string-safely [s]
(binding [*read-eval* false]
(read-string s)))
(read-string-safely "#=(eval (def x 3))")
=> RuntimeException EvalReader not allowed when *read-eval* is false. clojure.lang.Util.runtimeException (Util.java:219)
(read-string-safely "(def x 3)")
=> (def x 3)
(read-string-safely "#java.io.FileWriter[\"precious-file.txt\"]")
=> RuntimeException Record construction syntax can only be used when *read-eval* == true clojure.lang.Util.runtimeException (Util.java:219)
Что касается
Отправка макро считыватель макроса (#) и меченой литералы вызывается во время чтения. В Clojure данных нет представления, поскольку к тому времени все эти конструкции были обработаны. Насколько я знаю, нет никакой возможности построить синтаксическое дерево кода Clojure.
Для сохранения этой информации вам придется использовать внешний синтаксический анализатор. Либо вы катите свой собственный парсер, либо можете использовать генератор парсера, такой как Instaparse и ANTLR. Полная грамматика Clojure для любой из этих библиотек может быть трудно найти, но вы можете расширить одну из грамматик EDN, чтобы включить дополнительные формы Clojure. Быстрый google показал an ANTLR grammar for Clojure syntax, вы можете изменить его, чтобы поддерживать конструкты, которые отсутствуют при необходимости.
Существует также Sjacket библиотека, созданная для инструментов Clojure, которые должны содержать информацию об исходном коде. Это похоже на то, что вы пытаетесь сделать, но у меня нет никакого опыта с ним лично. Судя по тестам, у него есть поддержка макросов читателя в его синтаксическом анализаторе.
Может быть излишним, но взять посмотрите на [clojail] (https://github.com/flatland/clojail) –
Используйте read-string с \ * read-eval \ * установите значение false – Ankur
Док говорит, что даже с [\ * read-eval * false] это все еще не предназначен для обеспечения безопасности. И как анализировать код, который опирается на # = и читать макросы? Я ожидаю, что они каким-то образом появятся в структурах данных без фактического выполнения. –