世界を動かす技術を、日本語で。

ツリーシッターと言語サーバー

2026年1月22日原文(lambdaland.org)

概要

Tree-sitter は高速でエラー耐性のあるパーサ生成器であり、主に構文ハイライトに利用 Language Server はコード解析とインテリジェントな支援をエディタに提供 両者は役割が異なり、Tree-sitterは構文解析、Language Serverは意味解析が得意 LSP(Language Server Protocol)によりエディタとサーバ間の連携が標準化 Rustなど一部言語ではLanguage Serverによる高度なハイライトも可能

Tree-sitterとは何か

  • Tree-sitterパーサ生成器
  • プログラミング言語の 文法記述 を入力し、 構文解析プログラム を自動生成
  • 高速動作構文エラー耐性 が特徴
  • テキストエディタでの 構文ハイライト 用途に最適
    • 入力途中の 不完全なコード でもハイライトが崩れにくい
    • 従来の 正規表現ベース のハイライトはエラー時に壊れやすい
  • クエリ言語 を使い、構文木に対して 特定要素の検索 が可能
    • EmacsのCitar拡張などで Typst サポートに活用
  • 言語実装 に忠実なハイライト実現
    • 単なるパターンマッチではなく 言語エンジン同等の解析 が可能

Language Serverとは何か

  • Language Serverプログラム解析サービス
  • エディタに 記号の定義位置補完候補 などを提供
  • Language Server Protocol(LSP) でエディタとサーバが JSONメッセージ で通信
    • オープン標準 であり、任意の言語・エディタで利用可能
  • N×M問題 の解消
    • 以前は言語数N×エディタ数M分の個別実装が必要だった
    • LSPにより 各言語は1つのLanguage Server各エディタはLSP対応 で済む
  • ランタイムやコンパイラとの連携 により 意味的に正確な解析 が可能
    • 例:同名関数popが複数ある場合、 どのモジュールのものか正確に特定
  • dumb-jump のような単純ツールは スコープ判定が弱い が、Language Serverは強力

構文ハイライトにおけるLanguage Serverの活用

  • Language Server でも 構文ハイライト は可能
    • ただし、 Tree-sitterより複雑かつ重い 場合が多い
  • Emacsの eglot-semantic-tokens-mode でLSPベースのハイライト対応
    • Rustコードでの使用例あり
    • Tree-sitterベースのハイライト で十分なため、特別な理由がなければそちらを利用
  • Rust-analyzer など一部Language Serverは 変数のmutability (可変・不変)を区別してハイライト可能
    • 通常の構文ハイライトでは不可能な 詳細情報の可視化 が可能

まとめと所感

  • 本記事は Ashton Wiersdorf による 完全な人間執筆
  • LLM(大規模言語モデル)は 翻訳や単純作業の自動化 には有用
  • 複雑な部分は 自分で書いた方が速い 場合も多い
  • LLM生成文も役立つが、 本記事は人間の思考と意図を込めて執筆
  • 本物の意味を持つ文章 の価値と、それを作る楽しさ

Hackerたちの意見

: https://github.com/tree-sitter-grammars/tree-sitter-yaml

変だな、yaml-ts-modeは存在するのに?パーサーの取得方法が変わったのかな?

うーん… 特定の言語にArchlinuxのパッケージがないからって、その言語にtree-sitterのサポートがないわけじゃないよね?例えば、https://github.com/Goldziher/tree-sitter-language-pack にある長い言語リストを見てみて。RやYAML、Golang、他にもたくさん含まれてるよ。

tree-sitter-yamlは確実に存在するよ[1]。おそらく、まだArch用にパッケージ化されてないだけだね。それは貢献できることかも。

私のemacs設定には、以下のパーサーがインストールされてるよ:awk、bash、bibtex、blueprint、c、c-sharp、clojure、cmake、commonlisp、cpp、css、dart、dockerfile、elixir、glsl、gleam、go、gomod、heex、html、janet、java、javascript、json、julia、kotlin、latex、lua、magik、make、markdown、nix、nu、org、perl、proto、python、r、ruby、rust、scala、sql、surface、toml、tsx、typescript、typst、verilog、vhdl、vue、wast、wat、wgsl、yaml。

Goはここにあるよ: https://github.com/tree-sitter/tree-sitter-go Googleで探してみて。他のも多分どこかにあるはず。

ほとんどは言語パックに入ってるよね(https://github.com/Goldziher/tree-sitter-language-pack)。他のはちょっと最適じゃない答えだけど、最新のLLMを使って文法を生成してみたら、意外と良い感じにできたよ(数回の試行で)。とはいえ、構文ハイライトや製品に組み込む以上のことをするなら、もっと時間をかけた方がいいと思う。

https://tree-sitter.github.io/tree-sitter/#parsers https://github.com/tree-sitter/tree-sitter/wiki/List-of-pars...

これはオレンジとジュースの違いみたいなもんだね。オレンジを絞ってジュースを取り出すこともできるけど、それだけがオレンジの使い方じゃないし、ジュースを作る方法もそれだけじゃない。私はtree-sitterを使ってカスタムプログラミング言語を開発してるけど、CSTからASTにするためにはもう一手間かかる。でも全体的な開発体験は、手動でパーサーを作るよりずっと早いよ。

毎回Treesitterの素晴らしさを褒めるチャンスがあるときは、必ずその機会を利用してるよ。ほんと大好きなんだ。いろんなパーサージェネレーターを試してみたけど、TSのアプローチはシンプルでめちゃくちゃ良いから、もう他のは使わないと思う。反復速度のおかげで、まるで禅の境地に入ったみたいに、文法設計だけに集中できて、技術的な部分は気にしなくて済むんだ。

N00bな質問だけど、言語パーサーは「com.foo.bar.Bazはここで定義されている」みたいな具体的な情報をくれるよね。Tree-sitterもそういうことしてくれるの?それとも「このファイルにはBazのシンボル宣言がある」とか、「このファイルの別のところには‘com.foo.bar’のパッケージ宣言がある」って言って、結局自分で調べなきゃいけないの?

CSTからASTに移行するための追加ステップ これについて詳しく教えてもらえる?新しい言語のパーサーとしてtree-sitterを使うことを考えてるんだけど、複数の構文をサポートするかもしれない。パースツリーを共通のスキーマに変換するつもりなんだけど、それがターゲット言語になると思う。具体的な構文木と抽象構文木の違いがいまいち分からないんだけど、前者は言語の意味に関係ない情報、例えば空白とかを含むってこと?

Hacker Newsで議論の続きを見る