   "Creates a StringPushbackReader from a given string"
   (StringPushbackReader. (atom s)))
 
-;; Helper functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; predicates
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defn- whitespace?
   "Checks whether a given character is whitespace"

      reader
      (recur reader))))

(defn read-number
  [reader initch])

(defn read-string
  [reader initch])


(defn read-list
  [reader initch is-recursive])

(defn read-vector
  [reader initch is-recursive])

(defn read-map
  [reader initch is-recursive])

(defn read-symbol
  [reader initch is-recursive])


(defn read
  "Reads the first object from a PushbackReader. Returns the object read.
Returns sentinel if the reader did not contain any forms."
  [reader eof-is-error sentinel is-recursive]
  (let [ch read-char] 
    (if (not (nil? ch))
      (cond
       (whitespace? ch) (recur reader)
       (comment-prefix? ch) (recur (skip-line reader))
       (number-literal? reader) (read-number reader ch)
       (string-prefix? ch) (read-string reader ch)
       (list-prefix? ch) (read-list reader ch is-recursive)
       (vector-prefix? ch) (read-vector reader ch is-recursive)
       (map-prefix? ch) (read-map reader ch is-recursive)
       :default (read-symbol reader ch)))
    sentinel))


(defn read-all
  "Reads a lazy sequence of objects from a reader."
  [reader]
  (lazy-seq (cons (read reader) (read-all reader))))

(defn- list-prefix?
  "Checks whether the char is the start of a list literal"
  [ch]
  (= ch "("))

(defn- vector-prefix?
  "Checks whether the char is the start of a vector literal"
  [ch]
  (= ch "["))

(defn- map-prefix?
  "Checks whether the char is the start of a map literal"
  [ch]
  (= ch "{"))

(declare read rmacros)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; read helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn- skip-line
  "Advances the reader to the end of a line. Returns the reader"
