Как получить элемент по ключу после использования instaparse в clojure? - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь сделать компилятор для школьного проекта.Я новичок в clojure.Я сделал простую программу ( interpreting-lang-if ), которая может анализировать строку с использованием instaparse и возвращать вектор, подобный этому:

[:LangIF [:before_if "676767; "] [:condition_expression "0"] 
[:statements_OK "1; 2;"] [:statements_NOK "3+4;"] [:after_if ""]]

Как я могу получить "before_if"элемент из списка?

Я попытался понять функцию get, но я должен был что-то понять при использовании этой функции.

Вот код:

(prn (interpreting-lang-if "676767; if (0) {1; 2;}else{3+4;};"))
(get (interpreting-lang-if "676767; if (0) {1; 2;}else{3+4;};") :before_if)
(get :before_if (interpreting-lang-if "676767; if (0) {1; 2;}else{3+4;};"))

Ожидаемый результат должен быть "676767" вместо ноль .

Спасибо за вашу помощь.

Ответы [ 3 ]

0 голосов
/ 23 декабря 2018

Я обнаружил, что застежки-молнии могут быть полезны с Instaparse AST, особенно когда вам нужно найти определенный узел, а затем найти другой узел относительно него.Вот функция, которая просматривает узлы, чтобы найти тот, который соответствует предикату:

(require '[clojure.zip :as zip])

(defn zip-to
  ([loc pred direction]
   (loop [loc loc]
     (if (and loc (not (zip/end? loc)))
       (if (pred (zip/node loc))
         loc
         (recur (direction loc)))
       loc))))

Чтобы найти :before_if в вашем AST:

(-> [:LangIF
     [:before_if "676767; "]
     [:condition_expression "0"]
     [:statements_OK "1; 2;"]
     [:statements_NOK "3+4;"]
     [:after_if ""]]
  zip/vector-zip
  (zip-to #{:before_if} zip/next)
  zip/right
  zip/node)
0 голосов
/ 23 декабря 2018

Вы можете легко управлять древовидными структурами данных, используя библиотеку Tupelo Forest.Вот живой пример вашей проблемы :

(dotest
  (with-forest (new-forest)
    (let [data-hiccup  [:LangIF
                        [:before_if "676767; "]
                        [:condition_expression "0"]
                        [:statements_OK "1; 2;"]
                        [:statements_NOK "3+4;"]
                        [:after_if ""]]

          root-hid     (add-tree-hiccup data-hiccup)
          before-hid   (find-hid root-hid [:LangIF :before_if])
          before-node  (hid->node before-hid)
          before-value (grab :value before-node)]

      (is= before-node {:tupelo.forest/khids [], :tag :before_if, :value "676767; "})
      (is= before-value "676767; "))))

before-hid - указатель на нужный узел, который мы находим, указывая желаемый путь [:LangIF :before_if] от корневого узла,Затем мы можем преобразовать указатель во весь узел и извлечь :value из узла.Возможны многие дальнейшие манипуляции.См. документы и дополнительные примеры .

0 голосов
/ 23 декабря 2018

Если вы не знаете точную позицию предмета:

(->> [:LangIF [:before_if "676767; "] [:condition_expression "0"]
      [:statements_OK "1; 2;"] [:statements_NOK "3+4;"] [:after_if ""]]
     (tree-seq vector? rest)
     (filter vector?)
     (filter (comp (partial = :before_if) first))
     (first)
     (second))

или если вы хотите использовать призрак:

(let [A [:LangIF [:before_if "676767; "] [:condition_expression "0"]
       [:statements_OK "1; 2;"] [:statements_NOK "3+4;"] [:after_if ""]]]
    (select [1 1] A))

или с простым get:

(let [A [:LangIF [:before_if "676767; "] [:condition_expression "0"]
       [:statements_OK "1; 2;"] [:statements_NOK "3+4;"] [:after_if ""]]]
    (get (get A 1) 1))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...