Может ли молния Clojure, созданная поверх дерева объектов Java, работать в zip-фильтре? - PullRequest
4 голосов
/ 06 февраля 2011

Сейчас я склеиваю ANTLR и Clojure, пытаясь создать молнию Clojure поверх абстрактного синтаксического дерева, которое возвращает ANTLR.

AST - это набор объектов со вкусом Java, использующий CommonTree объекты для представления иерархии.

Я сделал молнию над CommonTree следующим образом:

(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-фильтра функция «авто» добавляет или удаляет метаданные из объекта. За исключением того, что простые старые объекты Java не могут иметь метаданные .

Я лаю не на том дереве? Или (более вероятно), я не понимаю zip-фильтр достаточно хорошо, чтобы скопировать его?

1 Ответ

2 голосов
/ 06 февраля 2011

Застежки-молнии хранят ветвь?, Потомки и делают функции как мета в loc, обертывающем узел, и кажется, что auto добавляет или удаляет мету в оболочку loc (вектор) вокруг объекта, а не сам объект. Так что я думаю, что это не проблема.

Можете ли вы объяснить больше о том, что "просто не работает"?

Одним из мест, которые выглядят подозрительно (и это сбило меня с толку обычными молниями), является функция branch?. Обратите внимание, что ваше первое and условие в token= проверяет branch? - если у токена нет дочерних элементов, оно не будет совпадать с token=, что может удивить. ветка? на самом деле говорит, возможно ли 1011 * для узла иметь детей, поэтому иногда вы хотите вернуть true, даже если у него на самом деле нет детей. Кроме этого, я не вижу ничего очевидного.

Примечание. В java->, поскольку у вас есть только одна опция, вы можете упростить анонимную функцию. Если это всегда строка, то вы можете просто заменить всю анонимную функцию на token=. Или, если вам нужно обработать не строковый регистр и вернуть nil, вы можете захотеть (when (string? %) (token= %)).

Я фактически атаковал почти такую ​​же проблему в прошлом по другому маршруту. Не уверен, что это поможет вообще, но на всякий случай ...

Я построил грамматику Antlr, которая выдает вывод, который я хотел пройти и изменить в Clojure как дерево. Решение, которое я выбрал, было:

  • Antlr грамматика ->
  • Грамматика древовидного дерева (массаж, независимость от языка) ->
  • Шаблоны строк Antlr (специфичные для Clojure) для генерации ->
  • Закрытие структур данных в виде строк ->
  • считывание структур данных Clojure во вложенное дерево (записи для нас, но может быть любым)

Одним из преимуществ этого было то, что код Antlr Java не зависел напрямую от кода Clojure (только в формате передаваемых строк), что делало код Clojure зависимым только от сгенерированного кода Java. Это немного упростило структуру зависимостей при компиляции проекта (я думаю, вы также достигли этого). Другое преимущество заключается в том, что грамматика и древовидная грамматика не зависели от языка, поэтому вы могли создавать Clojure и / или Java и / или другие цели из одной и той же грамматики (не то чтобы я это делал на самом деле).

...