Po pierwsze nie powinieneś nigdy czytać kodu clojure bezpośrednio z niezaufanych źródeł danych. Zamiast tego należy użyć EDN lub innego formatu serializacji.
Mówiąc to od czasu Clojure 1.5 istnieje pewien rodzaj bezpiecznego sposobu odczytywania ciągów bez ich oceniania. Powinieneś związać zmienną read-eval var z wartością false przed użyciem ciągu znaków do przeczytania. W Clojure 1.4 i wcześniejszych może to powodować skutki uboczne wywołane przez konstruktory Java. Te problemy zostały już naprawione.
Oto przykładowy kod:
(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)
chodzi czytelnik makra
Wysyłka makro (#) i oznaczone literały są wywoływane w czasie odczytu. Nie ma reprezentacji dla nich w danych Clojure, ponieważ do tego czasu wszystkie te konstrukty zostały przetworzone. O ile mi wiadomo, nie ma kompilacji w celu wygenerowania drzewa składni kodu Clojure.
Będziesz musiał użyć zewnętrznego parsera, aby zachować te informacje. Możesz uruchomić własny niestandardowy analizator składni lub użyć generatora analizatora składni, takiego jak Instaparse i ANTLR. Kompletna gramatyka Clojure dla każdej z tych bibliotek może być trudna do znalezienia, ale można rozszerzyć jedną z gramatyk EDN, aby uwzględnić dodatkowe formularze Clojure. Szybki google ujawnił an ANTLR grammar for Clojure syntax, możesz go zmienić, aby obsługiwał konstrukcje, których w razie potrzeby brakuje.
Istnieje również biblioteka stworzona dla narzędzi Clojure, które muszą zachować informacje o samym kodzie źródłowym. Wygląda na to, że dobrze pasuje do tego, co próbujesz zrobić, ale nie mam z nim żadnego osobistego doświadczenia. Sądząc z testów, posiada wsparcie dla makr czytnika w jego parserze.
Może być przesada, ale wziąć spójrz na [clojail] (https://github.com/flatland/clojail) –
Użyj łańcucha do odczytu z \ * read-eval \ * ustaw na false – Ankur
Doc mówi, że nawet z [\ * read-eval * false] it wciąż nie zaprojektowane, aby być bezpieczne. A jak analizować kod, który polega na # = i czytać makra? Oczekuję, że pojawią się one w strukturach danych bez faktycznego wykonania. –