在Java对象树上创建的Clojure拉链能否在zip筛选器中工作?
我目前正在将ANTLR和Clojure粘在一起,试图在ANTLR返回的抽象语法树上创建Clojure拉链 AST是一组非常Java风格的对象,使用对象表示层次结构 我在CommonTree上做了一个拉链,如下所示:在Java对象树上创建的Clojure拉链能否在zip筛选器中工作?,java,interop,clojure,antlr,Java,Interop,Clojure,Antlr,我目前正在将ANTLR和Clojure粘在一起,试图在ANTLR返回的抽象语法树上创建Clojure拉链 AST是一组非常Java风格的对象,使用对象表示层次结构 我在CommonTree上做了一个拉链,如下所示: (defn branch? [tn] (not (zero? (.getChildCount tn)))) (defn children [tn] (.getChildren tn)) (defn make [tn children] (doto (CommonTree. tn)
(defn branch? [tn] (not (zero? (.getChildCount tn))))
(defn children [tn] (.getChildren tn))
(defn make [tn children] (doto (CommonTree. tn)
(.addChildren children)))
(defn zip-parse [f] (z/zipper branch? children make (parse f)))
(我不能100%确定以这种方式制作CommonTree节点是否有效。我还没有做足够的工作来验证它…)
我使用以下函数:
(def zip-ast (parse testfile))
到目前为止,一切顺利。这确实有效。我可以使用“向下”、“向右”、“向左”和“向上”功能导航。当我尝试使用zip筛选器库查找特定令牌时,出现了问题:
(defn token [loc] (-> loc z/node .getToken .getText))
(defn token= [tokenname]
(fn [loc]
(filter #(and (z/branch? %) (= tokenname (token %)))
(if (zf/auto? loc)
(zf/children-auto loc)
(list (zf/auto true loc))))))
(defn java->
[loc & preds]
(zf/mapcat-chain loc preds #(cond (string? %) (token= %))))
这显然是从Chouser的尼斯xml->函数复制而来的。不幸的是,它根本不起作用。在zip筛选器中,函数“auto”添加或删除对象中的元数据。除此之外,普通的旧Java对象不能有元数据
我找错树了吗?或者(更可能的是),我对zip筛选器的理解还不足以复制它吗?Zipper存储分支、子项,并在包裹节点的loc上将函数作为meta,而auto似乎正在向对象周围的loc包装(向量)添加或移除meta,而不是对象本身。所以,我认为这不是问题 你能解释一下什么“就是不起作用”吗
分支?
功能是一个看起来可疑的地方(这让我被定制的拉链绊倒了)。请注意,您在令牌=
中的第一个和条件检查分支?
-如果令牌没有子项,它在令牌=
中将不匹配,这可能令人惊讶。分支机构?表示节点是否可能有子节点,因此有时您希望返回true,即使它实际上没有子节点。除此之外,我没有看到任何明显的变化
注意:在java->中,由于只有一个选项,因此可以简化匿名函数。如果它总是一个字符串,那么您只需将整个匿名函数替换为token=
。或者,如果需要处理非字符串大小写并返回nil,则可能需要(when(string?%)(token=%)
事实上,我在过去曾沿着不同的路线解决过几乎相同的问题。不确定这是否有帮助,但以防万一
我构建了一个Antlr语法,生成了我想在Clojure中作为树遍历和修改的输出。我最终想到的解决方案是:
- Antlr语法->
- Antlr树语法(按摩,语言不可知)->
- 要生成的Antlr字符串模板(特定于Clojure->
- Clojure数据结构作为字符串->
- 将Clojure数据结构读入嵌套树中(我们有记录,但可以是任何记录)
这样做的一个好处是Antlr Java代码不直接依赖Clojure代码(仅以传入字符串的格式),这使得Clojure代码只依赖于生成的Java代码。这在编译项目时稍微简化了依赖关系结构(我认为您也实现了这一点)。另一个好处是语法和树语法与语言无关,因此您可以使用相同的语法创建Clojure和/或Java和/或其他目标(我实际上并没有这样做) token=中第一个条件的捕获良好。这是我的错误,复制我不完全理解的代码。java->函数最终将支持其他条件,匿名函数的退化形式是因为我去掉了其他谓词来理解这个问题。总的来说,“只是不起作用”是当auto试图在CommonTree对象上使用meta执行时,我得到一个ClassCastException。with meta仅适用于IObj(即Clojure对象)的实现者。还可以使用Antlr“编译”成表示Clojure数据结构的字符串。。。哇!酷。我想。我可以看到这将如何减少Antlr的AST对象和Clojure函数之间的阻抗失配。不知怎么的,从旧金山到西雅图,还是感觉像是从芝加哥飞过来的。你能发布堆栈跟踪的相关部分吗?我猜上面的自动呼叫可能来自儿童
?对不起<代码>儿童自动
我是说?这是我看到的唯一在树节点上调用auto而不是loc的地方。IIRC,定制Antlr AST树节点非常容易。也许你可以创建一个节点类型,或者是一个带meta的IObj,或者有一个额外的映射,你可以在其中存储meta并破解zip过滤器来处理它。仔细想想,我的拉链功能似乎有问题。我在名称空间中定义了“branch?”和“children”,忽略了zip/branch?还有拉链/儿童?功能。我希望我的函数被调用,但是zip中的函数被调用,从loc中解包对象并用对象调用我的函数。