Prima di tutto non si dovrebbe mai leggere il codice del clojure direttamente da fonti di dati non attendibili. Dovresti invece usare EDN o un altro formato di serializzazione.
Ciò detto da Clojure 1.5 è una sorta di modo sicuro di leggere le stringhe senza evitarle. È necessario associare il valore read-eval var a false prima di utilizzare read-string. In Clojure 1.4 e precedenti questo poteva portare a effetti collaterali causati dal richiamo di costruttori java. Questi problemi sono stati risolti.
Ecco qualche esempio di codice:
(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)
Per quanto riguarda il lettore di macro
L'invio macro (#) e contrassegnati letterali vengono richiamati in fase di lettura. Non c'è alcuna rappresentazione per loro nei dati Clojure poiché da quel momento questi costrutti sono stati tutti elaborati. Per quanto ne so, non esiste un modo per generare un albero di sintassi del codice Clojure.
È necessario utilizzare un parser esterno per conservare tali informazioni. O arrotoli il tuo parser personalizzato o puoi usare un generatore di parser come Instaparse e ANTLR. Una grammatica Clojure completa per entrambe le librerie potrebbe essere difficile da trovare, ma è possibile estendere una delle grammatiche EDN per includere i moduli Clojure aggiuntivi. Un rapido google ha rivelato an ANTLR grammar for Clojure syntax, è possibile modificarlo per supportare i costrutti mancanti, se necessario.
C'è anche Sjacket una libreria creata per gli strumenti Clojure che devono conservare informazioni sul codice sorgente stesso. Sembra una buona idea per quello che stai cercando di fare ma non ho alcuna esperienza personale. A giudicare dai test ha il supporto per le macro del lettore nel suo parser.
fonte
2014-07-04 14:01:11
potrebbe essere un peso inutile, ma prendere un guarda [clojail] (https://github.com/flatland/clojail) –
Usa read-string con \ * read-eval \ * impostato su false – Ankur
Doc dice che anche con [\ * read-eval * false] ancora non progettato per essere sicuro. E come analizzare il codice che si basa su # = e leggere i macro? Mi aspetto che appaiano in qualche modo nelle strutture dati senza essere effettivamente eseguite. –