语法感知子串替换

Ada*_*deg 6 string syntax replace clojure tokenize

我有一个包含有效Clojure表单的字符串.我想替换它的一部分,就像使用assoc-in,但是将整个字符串作为标记处理.

=> (assoc-in [:a [:b :c]] [1 0] :new)
[:a [:new :c]]
=> (assoc-in [:a 
                [:b,, :c]] [1 0] :new)
[:a [:new :c]]
=> (string-assoc-in "[:a 
                       [:b,, :c]]" [1 0] ":new")
"[:a 
   [:new,, :c]]"
Run Code Online (Sandbox Code Playgroud)

我想写string-assoc-in.请注意,它的第一个和最后一个参数是字符串,它保留换行符和逗号.它在Clojure中可行吗?我发现最接近的是read哪些电话clojure.lang.LispReader,但我不知道它是如何工作的.

我想用它来读取Clojure源文件并进行一些修改显示它,保留文件的结构.

Mic*_*zyk 2

我认为这应该可行,完全通用,不需要自己的阅读器/解析器:

(defn is-clojure-whitespace? [c]
  (or (Character/isSpace c)
      (= \, c)))

(defn whitespace-split
  "Returns a map of true -> (maximal contiguous substrings of s
  consisting of Clojure whitespace), false -> (as above, non-whitespace),
  :starts-on-whitespace? -> (whether s starts on whitespace)."
  [s]
  (if (empty? s)
    {}
    (assoc (group-by (comp is-clojure-whitespace? first)
                     (map (partial apply str)
                          (partition-by is-clojure-whitespace? s)))
      :starts-on-whitespace?
      (if (is-clojure-whitespace? (first s)) true false))))

(defn string-assoc-in [s coords subst]
  (let [{space-blocks true
         starts-on-whitespace? :starts-on-whitespace?}
        (whitespace-split s)
        s-obj (assoc-in (binding [*read-eval* false] (read-string s))
                        coords
                        (binding [*read-eval* false] (read-string subst)))
        {non-space-blocks false}
        (whitespace-split (pr-str s-obj))]
    (apply str
           (if starts-on-whitespace?
             (interleave space-blocks (concat non-space-blocks [nil]))
             (interleave non-space-blocks (concat space-blocks [nil]))))))
Run Code Online (Sandbox Code Playgroud)

例子:

user> (string-assoc-in "[:a [:b,, :c]]" [1 0] ":new")
"[:a [:new,, :c]]"
Run Code Online (Sandbox Code Playgroud)

更新:哎哟,发现一个错误:

user> (string-assoc-in "[:a [:b,, :c\n]]" [1 0] ":new")
"[:a [:new,, :c]]\n"
Run Code Online (Sandbox Code Playgroud)

如果没关系的话我会喜欢它,但我想我必须尝试做点什么......叹息