Skip to content

Instantly share code, notes, and snippets.

@jensb1
Last active March 13, 2021 10:32
Show Gist options
  • Save jensb1/f33c8512b66dfdf4d84f55603a654a05 to your computer and use it in GitHub Desktop.
Save jensb1/f33c8512b66dfdf4d84f55603a654a05 to your computer and use it in GitHub Desktop.
Simple indent parser in Clojure
(ns analyze (:require
[clojure.string :refer [split starts-with? trim]]
[clojure.core :refer [tree-seq re-find]]))
(defn line-param [line]
(trim (str (second (re-find #"\s*(.*?):" (str line))))))
(defn line-value [line]
(trim (str (second (re-find #".*:(.*)" (str line))))))
(defn whitespace-start [s]
(if (nil? s)
0
(loop [sum 0
s s]
(if (not= (first s) \space)
sum
(recur (inc sum) (rest s))))))
(defn ->branch [line child-obj]
{(line-param line) child-obj})
(defn ->leaf [line]
{(line-param line) (line-value line)})
(defn partition-by-n [lines n] (partition-by #(= (whitespace-start %) n) lines))
(defn ->desc [lines]
(if (< (whitespace-start (first lines)) (whitespace-start (second lines)))
(second (partition-by-n lines (whitespace-start (first lines))))
nil))
(defn ->tree
([lines]
(->tree lines []))
([lines obj]
(loop [lines (filter #(not-empty %) lines)
obj obj]
(if (empty? lines)
obj
(recur
(drop (max 1 (inc (count (->desc lines)))) lines)
(merge obj (let [node (first lines)]
(if-let [children (->desc lines)]
(->branch node (->tree children {}))
(->leaf node)))))))))
(def lines "
Param 1:
Param 2:
Param 3: value3
Param 4: 12
Param 9: 12
Param 2:
Param 3: value5
Param 4: value6
")
(clojure.pprint/pprint (->tree (split lines #"\n")))
[{"Param 1"
{"Param 2" {"Param 3" "value3", "Param 4" {"Param 9" "12"}}}}
{"Param 2" {"Param 3" "value5"}}
{"Param 4" "value6"}]
nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment