Skip to content

Instantly share code, notes, and snippets.

@sordina
Created October 28, 2014 22:55
Show Gist options
  • Save sordina/6bcb30d9e2690e6e1f08 to your computer and use it in GitHub Desktop.
Save sordina/6bcb30d9e2690e6e1f08 to your computer and use it in GitHub Desktop.
Simple parser to convert a string into a tree representing the structure of indented lines.
(ns instap)
(defn text [l] (clojure.string/replace l #"^\s+" ""))
(assert (= (text " \t\t\t asdf") "asdf"))
(defn value [c]
(condp = c
\space 1
\tab 4
0 ))
(assert (= (value \space) 1))
(assert (= (value \tab ) 4))
(assert (= (value \x ) 0))
(defn indented [l]
(->> l
(re-find #"^\s+")
(map value)
(apply +)))
(assert (= (indented " hello") 3))
(assert (= (indented "\t\thello") 8))
(defn node [x xs] [x xs])
(assert (= (node 1 2) [1 2]))
(defn less-than [[ai _] [bi _]] (< ai bi))
(defn until-less-than [l ls] (split-with (partial less-than l) ls))
(assert (= (less-than [4 :x] [5 :y]) true))
(assert (= (less-than [6 :x] [5 :y]) false))
(assert (= (until-less-than [1 :a] [[2 :b] [1 :c] [:q :r]]) [[[2 :b]] [[1 :c] [:q :r]]]))
(defn line [[i l]] l)
(declare buildForest)
(defn null [] [])
(defn singleton [[l]] [ (node (line l) []) ])
(defn complex [[l & ls]] (let [[gt lt] (split-with (partial less-than l) ls)]
(cons (node (line l) (buildForest gt)) (buildForest lt))))
(defn buildForest [ls]
(condp = (count ls)
0 (null)
1 (singleton ls)
(complex ls)))
(assert (= (buildForest [[0 "a b c"]]) [["a b c" []]]))
(defn makeLine [l] [(indented l), (text l)])
(assert (= (makeLine " asdf") [4 "asdf"]))
(defn lines [l] (re-seq #"[^\n]+" l))
(assert (= (lines "asdf\nqwer") ["asdf" "qwer"]))
(defn notBlank [l] (re-find #"\S" l))
(assert (notBlank "foo"))
(defn parse [s] (->> s
lines
(filter notBlank)
(map makeLine)
buildForest
))
(assert (= (parse "abc\n def") [["abc" [["def" []]]]]))
; (parse "a b c\n d e f\n g h i")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment