首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从instaparse遍历解析树

如何从instaparse遍历解析树
EN

Stack Overflow用户
提问于 2015-04-10 08:02:31
回答 1查看 480关注 0票数 2

我在用Clojure和Instaparse做实验。我创造了一个小玩具语言,我被困在如何正确对待产生的树。我得到的是:

代码语言:javascript
复制
[:ClassDescription 
 [:ClassName "Test"]
 [:Properties 
  [:Property 
   [:PropertyName "ID"] 
   [:PropertyType "Int"]] 
  [:Property 
   [:PropertyName "Name"] 
   [:PropertyType "string"]]]]

现在,作为一个例子,我想提取所有的PropertyTypes。我有两种主要的方法,我想要解决这两种方法。

  1. 通过指定路径;类似于[:ClassDescription :Properties :Property :PropertyType]
  2. 通过提取所有:PropertyType元素,而不考虑深度。

对于A.,我的第一个想法是通过insta/transform将它的某些部分转换成映射,然后使用get-in,但之后我得到了一个非常笨拙的解决方案,涉及嵌套循环和get-in

我也可以使用nth,并在结构中钻研我自己,但这似乎很麻烦,如果我添加另一个层,就会很容易崩溃。

我的另一个想法是一种递归解决方案,我以相同的方式对待每个元素,并循环遍历它并检查所有匹配项。

对于B,到目前为止,我唯一的解决方案是一个递归函数,它只需要遍历所有内容并尝试匹配第一个元素。

我相信这些“手写”函数可以通过insta/transformmapfilterreduce等巧妙的组合来避免,可以吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-10 10:31:47

为了从解析的数据中获取元素,可以使用tree-seq迭代所有元素并选择所需的内容。例如:

代码语言:javascript
复制
(defn parsed-tree-seq [parsed]
  (tree-seq #(vector? (second %)) rest parsed))

(map second
     (filter
       #(= (first %) :PropertyType)
       (parsed-tree-seq parsed)))
; => ("Int" "string")

然而,您最好首先通过在解析器中使用<...>和/或将数据转换成更易于访问的地图来格式化您的数据。例如,将:Properties转换成一个地图列表,并将整个事物转化为一张地图:

代码语言:javascript
复制
(defn transform [parsed]
  (insta/transform
    {:Property #(into {} %&)
     :Properties #(vec (concat [:Properties] [%&]))
     :ClassDescription #(into {} %&)
     } parsed))

(map :PropertyType (:Properties (transform parsed)))
; => ("Int" "string")
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29556277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档