reader: one-char literals for non-symbol chars (\{ \( \, \%)
read-char read the char name with symbol-char?, so a literal whose char isn't a
symbol char (\{, \(, \), \,, \%, …) came back as an empty name and errored
'Unsupported character'. Now a single non-symbol char after \ is taken as a
one-character literal of that char. Surfaced by funcool/cuerdas (uses \{), which
now loads. Spec cases added.
This commit is contained in:
parent
b3a145f124
commit
d724aa7069
3 changed files with 18 additions and 5 deletions
|
|
@ -86,8 +86,9 @@ env read would be frozen at build).
|
||||||
libs and reports load/run status (network-gated behind `JOLT_CONFORMANCE=1`, so
|
libs and reports load/run status (network-gated behind `JOLT_CONFORMANCE=1`, so
|
||||||
CI stays offline). First run:
|
CI stays offline). First run:
|
||||||
- `medley` — loads and runs.
|
- `medley` — loads and runs.
|
||||||
- `cuerdas` — fails to load: the reader rejects a char/literal it uses
|
- `cuerdas` — now loads (it used `\{`, a one-char literal the reader rejected;
|
||||||
(`Unsupported character: \`). A genuine reader gap to chase.
|
fixed). A function (`kebab`) still hits a separate runtime gap — a smaller,
|
||||||
|
per-function issue rather than a whole-namespace failure.
|
||||||
- `stuartsierra/dependency` — `Long/MAX_VALUE`: JVM interop, so out of scope
|
- `stuartsierra/dependency` — `Long/MAX_VALUE`: JVM interop, so out of scope
|
||||||
(it isn't actually pure-`cljc`).
|
(it isn't actually pure-`cljc`).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,9 +314,15 @@
|
||||||
|
|
||||||
(defn read-char [s pos]
|
(defn read-char [s pos]
|
||||||
# pos is at backslash; produce a char value directly (self-evaluating)
|
# pos is at backslash; produce a char value directly (self-evaluating)
|
||||||
(let [end (read-char-name-end s (+ pos 1))
|
(when (>= (+ pos 1) (length s))
|
||||||
char-name (string/slice s (+ pos 1) end)]
|
(error "unexpected end of input after \\"))
|
||||||
[(char-from-name char-name) end]))
|
(let [end (read-char-name-end s (+ pos 1))]
|
||||||
|
(if (= end (+ pos 1))
|
||||||
|
# The char right after \ isn't a symbol char (e.g. \{ \( \, \% \" ): it's a
|
||||||
|
# one-character literal of that character itself.
|
||||||
|
[(make-char (s (+ pos 1))) (+ pos 2)]
|
||||||
|
(let [char-name (string/slice s (+ pos 1) end)]
|
||||||
|
[(char-from-name char-name) end]))))
|
||||||
|
|
||||||
(defn read-anon-fn [s pos]
|
(defn read-anon-fn [s pos]
|
||||||
# pos is at #, next char is (
|
# pos is at #, next char is (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@
|
||||||
["namespaced keyword" "true" "(= :a/b :a/b)"]
|
["namespaced keyword" "true" "(= :a/b :a/b)"]
|
||||||
["char" "\\a" "\\a"]
|
["char" "\\a" "\\a"]
|
||||||
["char newline" "true" "(= \\newline (first \"\\n\"))"]
|
["char newline" "true" "(= \\newline (first \"\\n\"))"]
|
||||||
|
# single non-symbol chars are one-char literals (\{ \( \, \% etc.)
|
||||||
|
["char open-brace" "123" "(int \\{)"]
|
||||||
|
["char open-paren" "40" "(int \\()"]
|
||||||
|
["char comma" "44" "(int \\,)"]
|
||||||
|
["char percent" "37" "(int \\%)"]
|
||||||
|
["char unicode" "65" "(int \\u0041)"]
|
||||||
["hex literal" "255" "0xff"]
|
["hex literal" "255" "0xff"]
|
||||||
["hex uppercase" "31" "0X1F"]
|
["hex uppercase" "31" "0X1F"]
|
||||||
["bigint suffix N" "42" "42N"]
|
["bigint suffix N" "42" "42N"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue