The primary suggestion I'd make here is to replace the doseq/reset! construction in your main loop with reduce using a hash-map accumulator representing each value you are updating with a separate key. This isn't just more idiomatic, it also performs better.
(let [hexagrams (atom (sorted-map))
state (atom :do-nothing)
current-hexagram (atom {})]
(doseq [line (line-seq rdr)]
(let [state-machine (@state PRETTY-STATE-MACHINE)
line-match (re-matches (:regex state-machine) line)
[new-state new-hexagram] ((:handler state-machine) line-match @current-hexagram)]
(reset! state new-state)
(reset! current-hexagram new-hexagram)
(swap! hexagrams assoc (:king-wen-number new-hexagram) new-hexagram))))
something like:
(reduce (fn [acc line]
(let [{:keys [state hexagrams current-hexagram]} acc
state-machine (state PRETTY-STATE-MACHINE)
line-match (re-matches (:regex state-machine) line)
[new-state new-hexagram] ((:handler state-machine) line-match current-hexagram)]
{:state new-state
:current-hexagram new-hexagram
:hexagrams (assoc (:king-wen-number new-hexagram) new-hexagram)}))
(line-seq rdr))