【问题标题】:How to postwalk parsely result?如何解析解析结果?
【发布时间】:2013-06-02 02:43:41
【问题描述】:

我正在查看一个使用 parsley 解析其语法的 clojure 重构库。 我将 parsley 升级到 0.9.1,然后一个功能失败了。

这是该函数的作用: 假设我们有"(defn a [b] (:foo b))",重构工具将解析参数并映射查找:[b](:foo b)。然后将(:foo b) 转换为地图:{b (foo :foo)} 并将[b] 中的符号b 替换为地图的值(foo :foo)。我终于应该得到{(foo :foo)}

以下代码用于最后一步:

clojure.walk/postwalk-replace {#net.cgrand.parsley.Node{:tag :atom, :content ["b"]} #net.cgrand.parsley.Node{:tag :map, :content ["{" #net.cgrand.parsley.Node{:tag :atom, :content ["foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} #net.cgrand.parsley.Node{:tag :atom, :content [":foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} "}"]}}
                           #net.cgrand.parsley.Node{:tag :vector, :content ["[" #net.cgrand.parsley.Node{:tag :atom, :content ["b"]} "]"]}

它报告:`UnsupportedOperationException Can't create empty: net.cgrand.parsley.Node net.cgrand.parsley.Node (parsley.clj:19)

但是,当我 pprint {#net.cgrand.parsley.Node{:tag :atom, :content ["b"]} #net.cgrand.parsley.Node{:tag :map, :content ["{" #net.cgrand.parsley.Node{:tag :atom, :content ["foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} #net.cgrand.parsley.Node{:tag :atom, :content [":foo"]} #net.cgrand.parsley.Node{:tag :whitespace, :content [" "]} "}"]}}

#net.cgrand.parsley.Node{:tag :vector, :content ["[" #net.cgrand.parsley.Node{:tag :atom, :content ["b"]} "]"]}

然后将它们传递给 postwalk:

(clojure.walk/postwalk-replace {{:tag :atom, :content ["b"]}
                            {:tag :map,
                             :content
                             ["{"
                              {:tag :atom, :content ["foo"]}
                              {:tag :whitespace, :content [" "]}
                              {:tag :atom, :content [":foo"]}
                              {:tag :whitespace, :content [" "]}
                              "}"]}}
                           {:tag :vector, :content ["[" {:tag :atom, :content ["b"]} "]"]})

一切都很好,我得到了我想要的{:content ["[" {:content ["{" {:content ["foo"], :tag :atom} {:content [" "], :tag :whitespace} {:content [":foo"], :tag :atom} {:content [" "], :tag :whitespace} "}"], :tag :map} "]"], :tag :vector}

我的问题是:#net.cgrand.parsley.Node 在欧芹中是什么意思?为什么在我删除这些符号(使用 pprint)之后问题就消失了。

【问题讨论】:

    标签: parsing xml-parsing clojure


    【解决方案1】:

    问题在于 Parsley 的节点是记录,而不是常规映射。 #net.cgrand.parsley.Node{...} 是此记录类型的文字符号。无法清空记录(与clojure.core/empty 一样),clojure.walk 函数依赖于使用empty 清空集合,因此clojure.walk 函数无法对记录进行操作。

    碰巧pprint在打印记录时省略了标签——它只是将它们打印为常规地图——所以如果你读回pprinted表示,你会得到一个地图,然后可以清空,所以你可以把它传递给postwalk

    正确的行动方案取决于您想要完成的具体目标。如果你想要实际的Node 实例,你需要编写自己的tree walker(也许适应clojure.walk/walk);如果您可以使用常规地图,您可以编写一个非常简单的树遍历器,用 Parsley 输出中的地图替换 Nodes,然后在转换后的树上使用 clojure.walk

    【讨论】:

    • 这是有道理的。看来我必须编写自己的 tree walker,因为 lib 在任何地方都使用 Node 实例。谢谢。
    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2015-09-15
    • 2018-07-20
    • 1970-01-01
    相关资源
    最近更新 更多