Next: , Previous: , Up: プログラムソースの解析   [Contents][Index]


37.3 ノードの取得

以下はわたしたちがtree-sitter関数を文書化する際に用いる用語と慣習についてです。

構文ツリーのノードは、バッファーのプログラムテキストのある部分に跨ります(span)。あるノードの跨ぐバッファーテキスト部分が、他のノードのそれより小さい(または大きい)場合には、わたしたちはそのノードが他のノードより“小さい”(または“大きい”)と表現します。ツリーにおいてより深い(“下位”の)ノードは、そのツリーのより“上位”ノードの子となるので、そのノード階層において下位のノードは常に上位のノードより小さくなります。構文ツリーの上位のノードには、その子として1つ以上の小さいノードが含まれており、したがってバッファーテキストのより大きい部分を跨ぐことになるのです。

関数がノードを見つけられなかった場合にはnilをリターンします。利便性のために、引数としてノードを受け取ってノードをリターンするすべての関数もnilの引数を許し、そのような場合には単にnilをリターンするようになっています。

関連付けられているバッファーが更新された際にノードが自動的に更新されることはなく、一度取得したノードを更新する術は存在しません。古くなってしまったノードを使用するとtreesit-node-outdatedエラーがシグナルされるでしょう。

構文ツリーからのノードの取得

Function: treesit-node-at pos &optional parser-or-lang named

この関数はバッファー位置posにある葉ノード(leaf node)をリターンする。葉ノードとは子ノードを何ももたないノードのこと。

この関数はposを跨がって覆う(cover)ようなノードのリターンを試みる。これは開始位置がpos以下、かつ終了位置がpos以上であるノードのこと。

posを跨いで覆うような葉ノードがない(たとえばposが2つの葉ノードの間にある空白にある)場合には、この関数はposの後にある最初の葉ノードをリターンする。

最後にもしposの後に葉ノードがなければ、posの前にある最初の葉ノードをリターンする。

parser-or-langがパーサーオブジェクトなら、この関数はそのパーサーを使用する。parser-or-langが言語の場合には、この関数はカレントバッファーにおいてその言語用の最初のパーサー、もし存在しなければパーサーを作成してそれを使用する。parser-or-langnilなら、この関数はtreesit-language-at (複数言語ののパースを参照)を呼び出して、posの言語の推測を試みる。

リターンする適切なノードが見つけられなかった場合には、この関数はnilをリターンする。

namedが非nilの場合には、この関数は名前つきのノードだけを探す(named nodeを参照)。

例:

;; Cパーサーの構文ツリーでポイント位置のノードを探す
(treesit-node-at (point) 'c)
  ⇒ #<treesit-node (primitive_type) in 23-27>
Function: treesit-node-on beg end &optional parser-or-lang named

この関数はbegendの間にあるバッファーテキストのリージョンを覆うような、もっとも小さいノードをリターンする。言い換えると開始がbeg以前、かつ終了がend以降であるようなノードのこと。

注意せよ: トップレベル構文(関数定義等)の内部ではない空行でこの関数を呼び出すと、恐らくルートノードが取得される場合がほとんどだろう。その空行を覆うもっとも小さいノードがルートノードだというのがその理由だが、あなたが使いたいと望んでいる機能は、ほとんどの場合はtreesit-node-atのほうだろう。

parser-or-langがパーサーオブジェクトなら、この関数はそのパーサーを使用する。parser-or-langが言語の場合には、この関数はカレントバッファーにおいてその言語用の最初のパーサー、もし存在しなければパーサーを作成してそれを使用する。parser-or-langnilなら、この関数はtreesit-language-at (複数言語ののパースを参照)を呼び出して、begの言語の推測を試みる。

namedが非nilの場合には、この関数は名前つきのノードだけを探す(named nodeを参照)。

Function: treesit-parser-root-node parser

この関数はparserが生成した構文ツリーのルートノードをリターンする。

Function: treesit-buffer-root-node &optional language

この関数はカレントバッファーでlanguage用の最初のパーサー、パーサーが存在しなければ作成して、そのパーサーが生成したルートノードをリターンする。languageが省略された場合にはパーサーリストの最初のパーサーを使用する。適切なパーサーが見つからなければnilをリターンする。

Lispプログラムはノードが与えられれば、そこから始まる他のノードを取得したり、そのノードに関する情報を問い合わせることができます。

ノードからの他ノードの取得

親族関係から

Function: treesit-node-parent node

この関数はnodeの直近の親をリターンする。

パースツリー(parse tree: 解析木)においてnodeが1000を超える深さのレベルにある場合のリターン値は未定義。現在のところnilをリターンするが、将来変更されるかもしれない。

Function: treesit-node-child node n &optional named

この関数はnoden番目の子をリターンする。namedが非nilなら名前つきのノードだけを考慮する(named nodeを参照)。

たとえば文字列"text"を表すノードの場合には開クォート"、文字列テキストのtext、それに閉クォート"という3つの子ノードが存在する。これら3つのノードの中で最初の子は開クォート"、最初の名前つきの子は文字列テキストとなる。

この関数はn番目の子が存在しなければnilをリターンする。nは負でも可(-1は最後の子を表す)。

Function: treesit-node-children node &optional named

この関数はnodeのすべての子をリストでリターンする。namedが非nilなら名前つきのノードだけを取得する。

Function: treesit-node-next-sibling node &optional named

この関数はnodeの次の兄弟を探す。namedが非nilなら次の名前つきの兄弟を探す。

Function: treesit-node-prev-sibling node &optional named

この関数はnodeの前の兄弟を探す。namedが非nilなら前の名前つきの兄弟を探す。

フィールド名から

構文ツリーの分析をより容易にするために、多くの言語ではグラマーで子ノードにフィールド名(field names)を割り当てています(field nameを参照)。たとえばfunction_definitionノードにはdeclaratorbodyというノードがあるかもしれません。

Function: treesit-node-child-by-field-name node field-name

この関数はフィールド名がfield-name(文字列)であるようなnodeの子を探す。

;; フィールド名が"body"という子を取得
(treesit-node-child-by-field-name node "body")
  ⇒ #<treesit-node (compound_statement) in 45-89>

位置から

Function: treesit-node-first-child-for-pos node pos &optional named

この関数はバッファー位置posを超えて広がるようなnodeの最初の子をリターンする。“超えて広がる(extends beyond)”とは子ノードの終端がpos以降であることを意味する。この関数はnodeの直接の子だけを調べる(孫は調べない)。namedが非nilの場合には最初の名前つきの子を探す(named nodeを参照)。

Function: treesit-node-descendant-for-range node beg end &optional named

これは位置begendの間にあるテキストリージョンを跨ぐような、もっとも小さいnodeの子孫ノードを探す、treesit-node-atと似た関数。namedが非nilの場合には、もっとも小さい名前つきの子を探す。

ノードの検索

Function: treesit-search-subtree node predicate &optional backward all depth

この関数はnodeのサブツリー(node自体を含む)を横断(traverse)して、predicateが非nilをリターンするようなノードを探す。predicateはノードそれぞれのタイプにたいしてマッチさせるregexp、あるいはノードを受け取りそのノードがマッチしたら非nilをリターンするような述語関数。この関数はマッチした最初のノード、何もマッチしなければnilをリターンする。

この関数が検索するのはデフォルトでは名前つきノードだけだが、allが非nilならすべてのノードを横断して検索を行う。backwardが非nilの場合には後方に横断して検索する(ツリーを下降して横断していく際に最後の子を最初に調べる)。depthが非nilなら、それはツリーを横断して下降できるレベル数を制限する数値でなければならない。depthnilの場合のデフォルトは1000。

Function: treesit-search-forward start predicate &optional backward all

この関数は(startを除けば)treesit-search-subtreeと同じようにパースツリーを横断して、predicateによりそれぞれのノードをマッチする(predicateはregexpまたは関数)。以下のようなツリー(‘S’マークはstart)の場合には、この関数は1から12の順に横断していく:

              12
              |
     S--------3----------11
     |        |          |
o--o-+--o  1--+--2    6--+-----10
|  |                  |        |
o  o                +-+-+   +--+--+
                    |   |   |  |  |
                    4   5   7  8  9

この関数はstartのサブツリーを横断せず、常に上方に移動する前にまず葉ノードを横断することに注意。

この関数が検索するのはtreesit-search-subtreeと同じようにデフォルトでは名前つきノードだけだが、allが非nilならすべてのノードを検索する。backwardが非nilの場合には後方に検索する。

treesit-search-subtreeはノードのサブツリーを横断するが、この関数はノードstartから開始してバッファーの位置順でその後にあるすべてのノード(開始位置がstartの終了位置より大きいノード)を横断する。

上図で示すツリーにおいて、treesit-search-subtreeはノード‘S’ (start)およびoのマークがついたノードを横断するが、この関数は数字のマークがついたノードを横断する。この関数は“バッファーでstartの後にあり何らかの条件を満足する最初のノードはどれ?”、のような問いの答えを求めるのに役に立つ。

Function: treesit-search-forward-goto node predicate &optional start backward all

この関数はバッファーでnodeの後にありpredicateにマッチする次のノードの開始または終了にポイントを移動する。startが非nilなら、ノードの終了ではなく開始で停止する。

この関数がリターンするマッチしたノードは、バッファー位置という点において進行方向にある(リターンされたノードの開始/終了はnodeのそれより常に大きい)ことが保証されている。

引数predicatebackwardalltreesit-search-forwardの場合と同じ。

Function: treesit-induce-sparse-tree root predicate &optional process-fn depth

この関数はrootのサブツリーからsparseツリー(疎らなツリー)を作成する。

この関数はroot配下のサブツリーを受け取って、predicateにマッチするノードだけが残るように間引く。前の関数と同じようにpredicateはノードそれぞれのタイプにマッチさせるためのregexp文字列、またはノードを受け取ってマッチした場合には非nilをリターンする。

たとえば数字と文字の両方で構成される左側のサブツリーが与えられた場合に、“文字のみ”というpredicateでリターンされるのが右側のツリー。

    a                 a              a
    |                 |              |
+---+---+         +---+---+      +---+---+
|   |   |         |   |   |      |   |   |
b   1   2         b   |   |      b   c   d
    |   |     =>      |   |  =>      |
    c   +--+          c   +          e
    |   |  |          |   |
 +--+   d  4       +--+   d
 |  |              |
 e  5              e

この関数はprocess-fnが非nilの場合には、マッチしたノードではなくノードをそれぞれprocess-fnに渡してリターン値を使用する。depthが非nilなら、それはrootから下降できるレベル数制限であること。depthnilの場合のデフォルトは1000。

リターンされるツリーのノードはそれぞれ(tree-sitter-node . (child …))のようになる。このツリーのルートであるtree-sitter-nodeは、rootpredicateにマッチしなければnilになる。predicateにマッチするノードがなければ、この関数はnilをリターンする。

より便利な関数

Function: treesit-filter-child node predicate &optional named

この関数はpredicateを満足するnodeの直接の子を探す。

predicateは引数としてノードを受け取り、そのノードを候補に残すべきなら非nilをリターンする関数であること。namedが非nilなら、この関数は名前つきのノードだけを調べる。

Function: treesit-parent-until node predicate &optional include-node

この関数はnodeの親を順繰りに探して、pred (引数としてノードを受け取りマッチを示すブーリーン値をリターンする関数)を満足する親をリターンする。predを満足する親がいなければ、この関数はnilをリターンする。

この関数は通常だとnode自体ではなくnodeの親だけを調べる。しかし、include-nodeが非nilの場合には、nodepredを満足すればnodeをリターンする。

Function: treesit-parent-while node pred

この関数はnodeを開始点としてノードがpred (引数としてノードを受け取る関数)を満足するかぎりツリーを上方に移動する。つまりこの関数はpredを満足するもっとも高位にあるnodeの親をリターンする。nodepredを満足して、かつ直近の親はpredを満足しなければ、node自体がリターンされることに注意。

Function: treesit-node-top-level node &optional type

この関数はnodeと同じタイプをもつ、もっとも高くにある親をリターンする。そのような親がいなければnilをリターンする。したがってこの関数はnodeがトップレベルかどうかをテストするためにも役に立つ。

typeが非nilの場合には、この関数はnodeのタイプではなく、regexpとしてtypeを用いてそれぞれの親のタイプをマッチする。


Next: ノード情報へのアクセス, Previous: tree-sitterパーサーの使用, Up: プログラムソースの解析   [Contents][Index]