Can a Clojure zipper filter created on a Java object tree work in a zip filter?

I am currently gluing ANTLR and Clojure trying to create a Clojure clasp over the abstract syntax tree returned by ANTLR.

AST is a very collection of objects with a Java flavor, using CommonTree to represent a hierarchy.

I made a zipper over 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 creating CommonTree nodes will work. I have not yet been convinced enough to check it ...)

I use the following functions:

 (def zip-ast (parse testfile)) 

So far so good. It really works. I can navigate with the functions "down", "right", "left" and "up". The problem occurs when I try to use the zip filter library to search for specific 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 brazenly copied from Chouser nice xml-> function. Unfortunately, this just doesn't work. Inside the zip filter, the "auto" function adds or removes metadata from the object. In addition, plain old Java objects cannot have metadata.

Am I barking the wrong tree? Or (more likely), don't I understand the mail filter well enough to copy it?

+4
source share
1 answer

Do zippers store the child branch ?, the children and perform functions like meta on the locus, wrapping the node, and it seems that auto adds or removes the meta in the loc shell (vector) around the object, not the object itself, so I think this is not a problem .

Can you explain in more detail that "just does not work"?

One place that looks suspicious (and it worked with regular lightning) is the branch? function branch? . Note that your first and condition in token= checks branch? - if the token does not have children, it will not match in token= , which may be surprising. branch? really says whether it is possible for a node to have children, so sometimes you want to return true there, even if it actually has no children. Other than this, I do not see anything obvious.

Note. In java->, since you have only one option, you can simplify the anonymous function. If it is always a string, then you can simply replace the entire anonymous function with only token= . Or, if you need to process a non-string register and return zero, you may need (when (string? %) (token= %)) .

I actually attacked almost the same problem in the past on a different route. Not sure if this helps at all, but just in case ...

I built an Antlr grammar that produced the output that I would like to go through and change in Clojure as a tree. I eventually decided:

  • Grammar Antlr →
  • Grammar of the tree Antlr (massage, language agnostic) →
  • Antlr string patterns (Clojure-specific) to generate →
  • Clojure data structures as strings →
  • read Clojure data structures in a nested tree (records for us, but can be any)

One of the advantages of this was that the Antlr Java code was not directly dependent on Clojure code (only in transmitted string format), which made Clojure code depend only on the generated Java code. This simplified the dependency structure when compiling the project (I think you did it too). Another advantage is that the grammar and grammar of the trees were agnostics of the language, so you could create Clojure and / or Java and / or other goals from the same grammar (not by the fact that I actually do this).

+2
source

Source: https://habr.com/ru/post/1338603/


All Articles