Skip to content

Instantly share code, notes, and snippets.

@amalantony
Last active February 13, 2017 23:22
Show Gist options
  • Save amalantony/d42d86cb24a1791450da9b60fb5fd43d to your computer and use it in GitHub Desktop.
Save amalantony/d42d86cb24a1791450da9b60fb5fd43d to your computer and use it in GitHub Desktop.
(ns anthology.json
(:require [clojure.string :as str]))
(def escape-characters
{\return "\\r"
\newline "\\n"
\tab "\\t"
\\ "\\\\"
\" "\\\""})
(defn write
[x]
(cond
(false? x) "false"
(keyword? x) (write-string (name x))
(number? x) (str x)
(nil? x) "null"
(true? x) "true"
(map? x) (yoke \{ (reduce (fn [c p] (conj c (str/join \: (map write-string p)))) [] x) \} )
(sequential? x) (yoke \[ (str/join \, (map write-string x)) \])
(string? x) (str \" (str/escape x escape-characters) \")))
(defn- read-false
[[a l s e & cs]]
(if (and (= a \a) (= l \l) (= s \s) (= e \e))
[cs false]
(throw (ex-info "" {}))))
(defn- read-null
[[u l l' & cs]]
(if (and (= u \u) (= l \l) (= l' \l))
[cs nil]
(throw (ex-info "" {}))))
(defn- read-true
[[r u e & cs]]
(if (and (= r \r) (= u \u) (= e \e))
[cs true]
(throw (ex-info "" {}))))
(defn- read-string
[[c & cs] s]
(if (= c \")
[cs s]
(recur cs (str s c))))
(def ^:private whitespace #{\newline \return \space \tab \,})
(declare read-array)
(defn read
[[c & cs]]
(if (contains? whitespace c)
(recur cs)
(case c
\[ (read-array cs [])
\" (read-string cs "")
\f (read-false cs)
\n (read-null cs)
\t (read-true cs)
(throw (ex-info "Unexpected token" {})))))
(defn- read-array
[cs buf]
(if (= (first cs) \])
[cs buf]
(let [[cs v] (read cs)]
(recur cs (conj buf v)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment