I'm presently gluing together ANTLR and Clojure, trying to create a Clojure zipper over the abstract syntax tree that ANTLR returns.
The AST is a very Java-flavored set of objects, using CommonTree objects to represent the hierarchy.
I made a zipper over the CommonTree as follows:
(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)))
(I'm not 100% sure that making CommonTree nodes that way will work. I haven't gotten far enough to verify it yet...)
I use these functions like this:
(def zip-ast (parse testfile))
So far, so good. This actually works. I can navigate with the "down", "right", "left", and "up" functions. The problem arises when I try to use the zip-filter library to locate particular tokens:
(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= %))))
This is blatantly copied from Chouser's nice xml-> function. Unfortunately, it just doesn't work. Inside zip-filter, the function "auto" adds or removes metadata from the object. Except, plain old Java objects can't have metadata.
Am I barking up the wrong tree? Or (more likely), do I not understand zip-filter well enough to copy it?