Skip to content

Commit b532b1f

Browse files
committed
[#65] Fix parsing of trailing uneval in reader conditional
1 parent cb9db91 commit b532b1f

File tree

3 files changed

+47
-23
lines changed

3 files changed

+47
-23
lines changed

script/read_core.clj

-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
(ns private.tmp.read-core)
2-
31
(require '[edamame.impl.parser :as p] :reload)
42
(require '[clojure.java.io :as io])
53
(def core (slurp (io/resource "clojure/core.clj")))
@@ -19,7 +17,6 @@
1917
(prn
2018
(meta (first nodes))))))
2119

22-
;; This is twice as fast... huh?
2320
"2"
2421
(time (dotimes [_ 10]
2522
(let [nodes (p/parse-string-all

src/edamame/impl/parser.cljc

+37-19
Original file line numberDiff line numberDiff line change
@@ -189,20 +189,34 @@
189189
(defn parse-first-matching-condition [ctx #?(:cljs ^not-native reader :default reader)]
190190
(let [features (:features ctx)]
191191
(loop [match non-match]
192-
(skip-whitespace ctx reader)
193-
(let [end? (= \) (r/peek-char reader))]
194-
(if end?
195-
(do (r/read-char reader) ;; ignore closing \)
196-
match)
197-
(let [k (parse-next ctx reader)
198-
match? (and (non-match? match)
192+
(let [k (parse-next ctx reader)]
193+
(if (identical? k ::expected-delimiter)
194+
match
195+
(let [next-is-match? (and (non-match? match)
199196
(or (contains? features k)
200197
(kw-identical? k :default)))]
201-
(if match? (recur (parse-next ctx reader))
202-
(do
203-
(parse-next (assoc ctx ::suppress true)
204-
reader)
205-
(recur match)))))))))
198+
(if next-is-match?
199+
(let [match (parse-next ctx reader)
200+
ctx (assoc ctx ::suppress true)]
201+
(loop []
202+
(let [next-val (parse-next ctx reader)]
203+
(when-not (identical? ::expected-delimiter
204+
next-val)
205+
(if (identical? ::eof next-val)
206+
(let [delimiter (::expected-delimiter ctx)
207+
{:keys [:row :col :char]} (::opened-delimiter ctx)]
208+
(throw-reader ctx
209+
reader
210+
(str "EOF while reading, expected " delimiter " to match " char " at [" row "," col "]")
211+
{:edamame/expected-delimiter (str delimiter)
212+
:edamame/opened-delimiter (str char)}))
213+
(recur)))))
214+
match)
215+
(do
216+
;; skip over next val and try next key
217+
(parse-next (assoc ctx ::suppress true)
218+
reader)
219+
(recur match)))))))))
206220

207221
(defn parse-reader-conditional [ctx #?(:cljs ^not-native reader :default reader)]
208222
(skip-whitespace ctx reader)
@@ -216,13 +230,17 @@
216230
(parse-next ctx reader)
217231
assoc :edamame/read-cond-splicing splice?))
218232
:else
219-
(do
220-
(r/read-char reader) ;; skip \(
221-
(let [match (parse-first-matching-condition ctx reader)]
222-
(cond (non-match? match) reader
223-
splice? (vary-meta match
224-
#(assoc % ::cond-splice true))
225-
:else match))))))
233+
(let [row (r/get-line-number reader)
234+
col (r/get-column-number reader)
235+
opened (r/read-char reader)
236+
ctx (assoc ctx
237+
::expected-delimiter \)
238+
::opened-delimiter {:char opened :row row :col col})
239+
match (parse-first-matching-condition ctx reader)]
240+
(cond (non-match? match) reader
241+
splice? (vary-meta match
242+
#(assoc % ::cond-splice true))
243+
:else match)))))
226244

227245
(defn get-auto-resolve
228246
([ctx reader next-val]

test/edamame/core_test.cljc

+10-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,16 @@
181181
{:read-cond identity})]
182182
(is (= '(:bb 1 :clj 2) res))
183183
(is (= {:row 1, :col 1, :end-row 2, :end-col 3, :edamame/read-cond-splicing true}
184-
(meta res)))))))
184+
(meta res)))))
185+
(testing "trailing uneval"
186+
(is (= 1 (p/parse-string "#?(#_(+ 1 2 3) :clj 2 #_112 :bb 1 #_112 )" {:read-cond true
187+
:features #{:bb}}))))
188+
(testing "EOF"
189+
(is (thrown-with-data? #"EOF while reading"
190+
{:edamame/expected-delimiter ")"
191+
:edamame/opened-delimiter "("}
192+
(p/parse-string "#?(#_(+ 1 2 3) :clj 2 #_112 :bb 1 #_112 " {:read-cond true
193+
:features #{:bb}}))))))
185194

186195
(deftest regex-test
187196
(is (re-find (p/parse-string "#\"foo\"" {:dispatch {\# {\" #(re-pattern %)}}}) "foo"))

0 commit comments

Comments
 (0)