Skip to content

Instantly share code, notes, and snippets.

@rundis
Created April 23, 2015 10:23
Show Gist options
  • Save rundis/77237558ca31aa5af5bf to your computer and use it in GitHub Desktop.
Save rundis/77237558ca31aa5af5bf to your computer and use it in GitHub Desktop.
Failed sexpr finder
(ns parser
(:require [clojure.tools.reader :as reader]
[clojure.tools.reader.reader-types :as rt]
[clojure.zip :as zip]))
(defn try-read [rdr]
(when rdr
(reader/read rdr false ::EOF)))
(defn lined-read [string]
(let [rdr (rt/indexing-push-back-reader string)]
(take-while #(not= ::EOF %) (repeatedly #(try-read rdr)))))
(defn in-form? [{:keys [line column end-line end-column]} pos]
(and (some #{(:line pos)} (range line (inc end-line)))
(some #{(:ch pos)} (range (inc column) end-column))))
(defn code->zip [code-str]
(-> code-str lined-read zip/seq-zip))
(defn find-sexpr [cur pos]
(cond
(zip/end? cur) nil
(not (list? (zip/node cur))) (find-sexpr (zip/next cur) pos)
:else (if (in-form? (meta (zip/node cur)) pos)
(if-let [child (find-sexpr (zip/next cur) pos)]
child
{:form-str (pr-str (zip/node cur))
:meta (meta (zip/node cur))})
(find-sexpr (zip/next cur) pos))))
(def sample "
(defn jalla
\"Jalla functions rules\"
[a b]
(let [dill (str a b)] ; yeah this makes a lot of sense right ?
(println (str \"jalla\" dill))))
; What on earth
(def a 4)")
(find-sexpr (code->zip sample) {:line 6 :ch 24}) ; ok
; DOH ! returns the let ..
; because zip/seq-zip well expect nested sequences, so vectors become a leaf node...
(find-sexpr (code->zip sample) {:line 5 :ch 16})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment