**Show HN: Tree‑Sitter を Go に移植しました**

Tree‑Sitter のパーサライブラリを C から Go に完全に移植し、使用できる状態になりました。

- **なぜ?**  
  - Go プロジェクトとの統合が容易になります。  
  - C‑Go バインディングとその落とし穴を回避できます。  

- **含まれる内容は?**  
  - コア API 全般(パーサ作成、文法読み込み、構文木走査)。  
  - 元の C テストスイートに合わせた最小限のテストセット。  

- **使い方**  
  ```go
  import "github.com/yourrepo/tree-sitter-go"

  parser := treesitter.NewParser()
  parser.SetLanguage(treesitter.Go)
  root := parser.Parse(nil, sourceCode)
  ```
  (詳細は README のサンプルをご覧ください。)

- **パフォーマンス**  
  - ベンチマークでは、ほとんどのワークロードで C バージョンに匹敵する速度を確認。  
  - Go の GC によりメモリ使用量がわずかに増加します。  

- **ロードマップ**  
  - 増分パース(incremental parsing)のサポート追加。  
  - 現在のサブセットを超える言語文法への拡張。  

ぜひ試してみてください。問題があれば報告、あるいは貢献も歓迎します!

2026/02/26 3:28

**Show HN: Tree‑Sitter を Go に移植しました** Tree‑Sitter のパーサライブラリを C から Go に完全に移植し、使用できる状態になりました。 - **なぜ?** - Go プロジェクトとの統合が容易になります。 - C‑Go バインディングとその落とし穴を回避できます。 - **含まれる内容は?** - コア API 全般(パーサ作成、文法読み込み、構文木走査)。 - 元の C テストスイートに合わせた最小限のテストセット。 - **使い方** ```go import "github.com/yourrepo/tree-sitter-go" parser := treesitter.NewParser() parser.SetLanguage(treesitter.Go) root := parser.Parse(nil, sourceCode) ``` (詳細は README のサンプルをご覧ください。) - **パフォーマンス** - ベンチマークでは、ほとんどのワークロードで C バージョンに匹敵する速度を確認。 - Go の GC によりメモリ使用量がわずかに増加します。 - **ロードマップ** - 増分パース(incremental parsing)のサポート追加。 - 現在のサブセットを超える言語文法への拡張。 ぜひ試してみてください。問題があれば報告、あるいは貢献も歓迎します!

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

gotreesitter は、Go と WebAssembly でネイティブに動作する Tree‑Sitter ランタイムの純粋な Go 実装です。CGo や外部ツールチェーンを必要とせず、同じパーステーブル形式(アップストリーム Tree‑Sitter と同一)を使用しているため、205 のサポート言語(204 つの「完全」文法+1 つの部分的文法)が再コンパイルなしで動作します。ベンチマークでは、インクリメンタル編集時に CGo バインディングより約 90 倍 速く、単一バイト編集は ~1 µs(CGo は ~124 µs)です。また、フルパースでは約 1.5 倍 速い(≈1 330 µs 対 2 058 µs)。API には

NewParser
Edit
ParseIncremental
があり、クエリ実行 (
NewQuery
Exec
、ストリーミングカーソル) と構文ハイライトやシンボルトラッキングなどの機能が提供されます。グラムマーブロブは圧縮保存され、初回使用時に遅延ロードされ、オプションで mmap サポートとキャッシュ制限があります。本ライブラリはスモークテスト、ゴールデン S‑式スナップショット、ハイライト検証、クエリエンジンチェック、パーサ正確性テスト、およびファズ (
FuzzGoParseDoesNotPanic
) で厳密にテストされています。今後の作業としては、クエリエンジンの整合性強化、外部スキャナ追加、明示的なパースエラー返却、自動パリティテスト(C 実装との比較)、ファズカバレッジ拡大などが挙げられます。プロジェクトは MIT ライセンスです。

本文

gotreesitter
純粋Goで実装された tree‑sitter ランタイム ― CGo も C ツールチェーンも不要、WASM に対応済み

go get github.com/odvcencio/gotreesitter

tree‑sitter が使用するパーステーブル形式をそのまま実装しているため、既存の文法は再コンパイル無しで動作します。
CGo バインディングよりもすべてのワークロードで高速です ― エディタや言語サーバーで最頻操作となる incremental edits は C 実装に比べ 90 倍速です。


なぜ CGo を使わないのか?

既存の Go 用 tree‑sitter バインディングはすべて CGo を必要とします。すると次のような問題が発生します。

  • クロスコンパイルが失敗する(例:
    GOOS=wasip1 GOARCH=arm64
    で Linux からビルド、Windows では MSYS2 が必須)
  • CI パイプラインはすべてのビルドイメージに C ツールチェーンをインストールしなければならない
  • go install
    は gcc が無い環境で失敗する
  • ランタイム検出、フィジング、カバレッジツールは CGo 境界でうまく機能しない

gotreesitter は純粋 Go です。どのターゲット・プラットフォームでも

go get
build
が可能です。


クイックスタート

import (
    "fmt"

    "github.com/odvcencio/gotreesitter"
    "github.com/odvcencio/gotreesitter/grammars"
)

func main() {
    src := []byte(`package main

func main() {}
`)

    lang := grammars.GoLanguage()
    parser := gotreesitter.NewParser(lang)

    tree := parser.Parse(src)
    fmt.Println(tree.RootNode())

    // ソースを編集した後はインクリメンタルに再パース
    //   tree.Edit(edit)
    //   tree2 := parser.ParseIncremental(newSrc, tree)
}

クエリ

tree‑sitter の S‑expression クエリ言語(predicate と cursor ベースのストリーミング)をサポートしています。現在の制約は Known Limitations を参照してください。

q, _ := gotreesitter.NewQuery(`(function_declaration name: (identifier) @fn)`, lang)
cursor := q.Exec(tree.RootNode(), lang, src)

for {
    match, ok := cursor.NextMatch()
    if !ok { break }
    for _, cap := range match.Captures {
        fmt.Println(cap.Node.Text(src))
    }
}

インクリメンタル編集

初回パース後、変更箇所だけを再パースします ― それ以外のサブツリーは自動的に再利用されます。

// 初期パース
tree := parser.Parse(src)

// ユーザーがバイトオフセット 42 に「x」を入力したとする
src = append(src[:42], append([]byte("x"), src[42:]...)...)

tree.Edit(gotreesitter.InputEdit{
    StartByte:   42,
    OldEndByte:  42,
    NewEndByte:  43,
    StartPoint:  gotreesitter.Point{Row: 3, Column: 10},
    OldEndPoint: gotreesitter.Point{Row: 3, Column: 10},
    NewEndPoint: gotreesitter.Point{Row: 3, Column: 11},
})

// インクリメンタル再パース – CGo バインディングより約1.38 µs vs 124 µs(90×高速)
tree2 := parser.ParseIncremental(src, tree)

ヒント:

grammars.DetectLanguage("main.go")
を使えばファイル名から適切な文法を自動選択できます ― エディタ統合に便利です。

シンタックスハイライト

hl, _ := gotreesitter.NewHighlighter(lang, highlightQuery)
ranges := hl.Highlight(src)

for _, r := range ranges {
    fmt.Printf("%s: %q\n", r.Capture, src[r.StartByte:r.EndByte])
}

注意:テキスト predicate(

#eq?
,
#match?
,
#any‑of?
,
#not‑eq?
)はソース
[]byte
を評価対象とします。
nil
を渡すと predicate チェックが無効化されます。

シンボルタグ付け

定義・参照を抽出します。

entry := grammars.DetectLanguage("main.go")
lang   := entry.Language()

tagger, _ := gotreesitter.NewTagger(lang, entry.TagsQuery)
tags := tagger.Tag(src)

for _, tag := range tags {
    fmt.Printf("%s %s at %d:%d\n", tag.Kind, tag.Name,
        tag.NameRange.StartPoint.Row, tag.NameRange.StartPoint.Column)
}

パース品質

LangEntry
Quality
フィールドを公開し、パース結果の信頼性を示します。

Quality意味
fullToken source または DFA + 外部スキャナー – 完全な忠実度
partialDFA‑partial – 外部スキャナーが欠落。ツリーに隠れたギャップが存在する可能性あり
noneパースできない
entries := grammars.AllLanguages()
for _, e := range entries {
    fmt.Printf("%s: %s\n", e.Name, e.Quality)
}

ベンチマーク

go-tree-sitter
(標準 CGo バインディング)と比較し、500 関数定義を含む Go ソースファイルのパース結果を測定しました。

Benchmarkns/opB/opallocs/op
CTreeSitterGoParseFull2 058 0006006
CTreeSitterGoParseIncrementalSingleByteEdit124 1006487
CTreeSitterGoParseIncrementalNoEdit121 1006006
GoParseFull1 330 00010 8422 495
GoParseIncrementalSingleByteEdit1 3813619
GoParseIncrementalNoEdit8.6300

まとめ

ワークロードgotreesitterCGo バインディング比率
Full parse1 330 µs2 058 µs約1.5×高速
Incremental (single‑byte edit)1.38 µs124 µs約90×高速
Incremental (no‑op reparse)8.6 ns121 µs約14 000×高速

インクリメンタルのホットパスはサブツリーを積極的に再利用します ― 1 バイト編集でマイクロ秒単位、CGo バインディングでは C ランタイムと呼び出しオーバーヘッドがかかります。no‑edit の高速経路は nil チェックのみで終了:割り当てゼロ、数ナノ秒。

対応言語

レジストリには 205 個の文法が付属しています。

go run ./cmd/parity_report
を実行してリアルタイムの言語別ステータスを確認してください。

  • 204 full – エラーなしでパース(Token source または DFA + 完全な外部スキャナー)
  • 1 partial – norg(122 トークンの外部スキャナーが必要、まだ実装未完了)
  • 0 unsupported

バックエンド別内訳:

BackendCount
dfa195
dfa‑partial1
token_source9

111 の言語は

zzz_scanner_attachments.go
に Go で実装された外部スキャナーを持っています。

全言語リスト(205):

ada, agda, angular, apex, arduino, asm, astro, authzed, awk, bash, bass,
beancount, bibtex, bicep, bitbake, blade, brightscript, c, c_sharp, caddy,
cairo, capnp, chatito, circom, clojure, cmake, cobol, comment, commonlisp,
cooklang, corn, cpon, cpp, crystal, css, csv, cuda, cue, cylc, d, dart,
desktop, devicetree, dhall, diff, disassembly, djot, dockerfile, dot,
doxygen, dtd, earthfile, ebnf, editorconfig, eds, eex, elisp, elixir,
elm, elsa, embedded_template, enforce, erlang, facility, faust, fennel,
fidl, firrtl, fish, foam, forth, fortran, fsharp, gdscript, git_config,
git_rebase, gitattributes, gitcommit, gitignore, gleam, glsl, gn, go,
godot_resource, gomod, graphql, groovy, hack, hare, haskell, haxe, hcl,
heex, hlsl, html, http, hurl, hyprlang, ini, janet, java, javascript,
jinja2, jq, jsdoc, json, json5, jsonnet, julia, just, kconfig, kdl,
kotlin, ledger, less, linkerscript, liquid, llvm, lua, luau, make,
markdown, markdown_inline, matlab, mermaid, meson, mojo, move, nginx,
nickel, nim, ninja, nix, norg, nushell, objc, ocaml, odin, org, pascal,
pem, perl, php, pkl, powershell, prisma, prolog, promql, properties,
proto, pug, puppet, purescript, python, ql, r, racket, regex, rego,
requirements, rescript, robot, ron, rst, ruby, rust, scala, scheme,
scss, smithy, solidity, sparql, sql, squirrel, ssh_config, starlark,
svelte, swift, tablegen, tcl, teal, templ, textproto, thrift, tlaplus,
tmux, todotxt, toml, tsx, turtle, twig, typescript, typst, uxntal, v,
verilog, vhdl, vimdoc, vue, wgsl, wolfram, xml, yaml, yuck, zig

クエリ API

機能状態
コンパイル + 実行 (
NewQuery
,
Execute
,
ExecuteNode
)
対応
Cursor ストリーミング (
Exec
,
NextMatch
,
NextCapture
)
対応
構造量化子(
? * +
対応
交差(
[…]
対応
フィールドマッチ (
name: (identifier)
)
対応
#eq? / #not‑eq?
対応
#match? / #not‑match?
対応
#any‑of? / #not‑any‑of?
対応
#lua‑match?
対応
#has‑ancestor? / #not‑has‑ancestor?
対応
#not‑has‑parent?
対応
#is? / #is‑not?
対応
#set! / #offset!
ディレクティブ
解析し受け入れ

現在の制限

  • クエリコンパイラギャップ – 2026年2月23日現在、本リポジトリ内で配布されているハイライト・タグクエリはすべてコンパイル可能(
    HighlightQuery
    156/156、
    TagsQuery
    69/69)
  • DFA‑partial 言語norg は外部スキャナーが未移植。DFA ラッカーのみでパースし、外部スキャナーに必要なトークンは無視されます。ツリー構造は有効ですがギャップが存在する可能性があります。
    entry.Quality
    を確認して full/partial を判別してください。

言語追加手順

  1. grammars/languages.manifest
    に文法を追加

  2. バインディング生成:

    go run ./cmd/ts2go -manifest grammars/languages.manifest \
      -outdir ./grammars -package grammars -compact=true
    

    これにより

    grammars/embedded_grammars_gen.go
    grammars/grammar_blobs/*.bin
    、言語レジストリスタブが再生成されます。

  3. cmd/parity_report/main.go
    grammars/parse_support_test.go
    にスモークサンプルを追加

  4. 確認:

    go run ./cmd/parity_report
    go test ./grammars/...
    

アーキテクチャ

gotreesitter は tree‑sitter ランタイムを純粋 Go で再実装しています。

  • Parser – テーブル駆動 LR(1)、曖昧文法用 GLR サポート
  • Incremental reuse – cursor ベースのサブツリー再利用。変更されていない領域はパースを完全にスキップ
  • Arena allocator – スラブベースノード割り当て、参照カウントで GC 負荷最小化
  • DFA lexer
    ts2go
    で生成されたテーブルから作成。必要に応じて手書きブリッジも用意
  • External scanner VM – 言語固有のスキャン(Python のインデントなど)を実行するバイトコード解釈器
  • Query engine – S‑expression パターンマッチング、predicate 評価、ストリーミング cursor
  • Highlighter – クエリベースのシンタックスハイライト(インクリメンタル対応)
  • Tagger – タグクエリを用いたシンボル定義・参照抽出

文法テーブルは upstream tree‑sitter の

parser.c
から
ts2go
ツールで抽出し、圧縮バイナリブロブにシリアライズ。最初の言語使用時に遅延ロードします。パース実行中に C コードは走りません。

ビルド時に

-tags grammar_blobs_external
を付与して
GOTREESITTER_GRAMMAR_BLOB_DIR
を設定すると、バイナリ内にブロブを埋め込まず外部ファイルとしてロードできます。Unix ではデフォルトで mmap が使用されます(
GOTREESITTER_GRAMMAR_BLOB_MMAP=false
で無効化)。

小さな埋め込みバイナリを作成したい場合は

-tags grammar_set_core
を付与してコア言語セット(c, go, java, javascript, python, rust, typescript 等)だけを含めることができます。

ランタイムで登録される言語を制限するには:

GOTREESITTER_GRAMMAR_SET=go,json,python

長時間稼働するプロセスでは、グラマキャッシュメモリは調整可能です:

// 直近に使用した 8 個のデコード済み文法だけを保持
grammars.SetEmbeddedLanguageCacheLimit(8)

// 一つの言語ブロブ(例: "rust.bin")をキャッシュから削除
grammars.UnloadEmbeddedLanguage("rust.bin")

// キャッシュ内のすべてのデコード済み文法を破棄
grammars.PurgeEmbeddedLanguageCache()

また、起動時に

GOTREESITTER_GRAMMAR_CACHE_LIMIT
を設定してキャッシュ上限を適用できます。0 にすると明示的に保持しないことを意味します(毎回デコードが再実行されます)。

アイドル退避は環境変数で有効化可能です:

GOTREESITTER_GRAMMAR_IDLE_TTL=5m
GOTREESITTER_GRAMMAR_IDLE_SWEEP=30s

ロード時のコンパクション/インターンはデフォルトで有効。以下を通じて調整できます:

GOTREESITTER_GRAMMAR_COMPACT=true
GOTREESITTER_GRAMMAR_STRING_INTERN_LIMIT=200000
GOTREESITTER_GRAMMAR_TRANSITION_INTERN_LIMIT=20000

テスト

テストスイートは以下を含みます。

  • Smoke tests – 205 個の文法すべてがサンプルでクラッシュせず
    ERROR
    ノードも生成しないことを確認
  • Correctness snapshots – コア言語 20 種類のゴールデン S‑expression テストでパーサと文法の回帰検出
  • Highlight validation – コンパイル済みハイライトクエリが正しくハイライト範囲を生成するか End‑to‑End テスト
  • Query tests – パターンマッチ、predicate、cursor、フィールドベースマッチングの検証
  • Parser tests – インクリメンタル再パース、エラー回復、GLR アンビギュイティ解消
  • Fuzzing
    FuzzGoParseDoesNotPanic
    でパーサの堅牢性を確認

実行例:

go test ./... -race -count=1

ロードマップ

現状:v0.4.0 ― 205 文法、安定したパーサ、インクリメンタル再パース、クエリエンジン、ハイライト、タグ付け。

次のステップ:

  • クエリエンジンの完全性強化 – フィールド否定セマンティクス、メタデータディレクティブ挙動、アップストリーム tree‑sitter との細部一致
  • 高価値 DFA‑partial 言語への手書き外部スキャナー追加
  • Parse() (*Tree, error)
    – エラーを返却(silent nil 木ではなく)
  • C tree‑sitter 出力とのパリティ自動テスト化
  • フィジング拡張でより多くの言語とクエリエンジンをカバー

ライセンス

MIT


同じ日のほかのニュース

一覧に戻る →

2026/02/26 5:16

ジミ・ヘンドリックスはシステムズエンジニアでした。

## Japanese Translation: ## Summary: この記事は、ジミ・ヘンドリックスを実質的にシステムエンジニアとして描き、彼が1967年の象徴的な「Purple Haze」のサウンドをペダルとアンプからなる意図的に設計された信号チェーンで作り出したことを論じています。Fuzz Face、Octavia(オクターブ倍増)、wah‑wah、Marshall amp、そして後のUni‑Vibeがどのように連携し、オクターブ倍増、バンドパスフィルタリング、位相シフト、および持続的なフィードバックを生成したかを説明しています。これらは単なる音楽的選択ではなく、設計されたサウンド挙動であると述べています。詳細な回路図を入手し、各ペダルをngspiceの回路シミュレータでモデル化することで、著者はPythonスクリプトを用いてオリジナル録音の非線形ダイナミクスを再現しました。本稿は、1967年2月3日にロンドンのOlympic Studiosで録音された歴史的背景を示し、ヘンドリックスがギターを静的なノブではなく身体運動によって操作するモジュラーアナログシステムとして扱ったことを強調しています。GitHubに公開されているさらなるシミュレーションコードは、他の音楽家がこれらのテクニックを再現または拡張できるようにし、パフォーマンスと回路設計を融合した新しいペダルデザインへのインスピレーションとなる可能性があります。このアプローチは、ギタリスト、プロデューサー、およびメーカーがより体系的なトーン形成方法を採用し、機材をエンジニアリングされたシステムとして捉えるよう促すでしょう。 ## Summary Skeleton **テキストの主な伝えたいこと(メインメッセージ)** この記事はジミ・ヘンドリックスをシステムエンジニアと描き、彼が1967年に「Purple Haze」をレコーディングした際に、ペダルとアンプからなる意図的に設計された信号チェーンを用いて表現力豊かなサウンド効果を生み出したことを示しています。 **証拠/根拠(なぜそう言われるのか)** - ヘンドリックスのチェーン――Fuzz Face、Octavia、wah‑wah、Marshall amp、後にUni‑Vibe――は、オクターブ倍増、バンドパスフィルタリング、位相シフト、および持続的なフィードバックを導入するカスタムハードウェアから構成されていました。 - 著者は詳細な回路図を取得し、ngspiceで各ペダルをモデル化し、Pythonスクリプトで連鎖したシミュレーションを行うことで、録音に観測された非線形挙動を再現しました。 **関連事例/背景(文脈・過去の出来事・周辺情報)** - 「Purple Haze」は1967年2月3日にロンドンのOlympic StudiosでRoger MayerのOctaviaペダルとともに録音されました。 - ヘンドリックスのアプローチは、ギターを静的なコントロールではなく身体運動によって操作するモジュラーアナログシステムとして扱いました。 - 本稿は2026年3月に印刷で掲載され、「Jimi Hendrix, Systems Engineer」というタイトルで、彼の音楽的革新と工学原理を結びつけています。 **今後起こりうること(将来の展開/予測)** - さらに進められたシミュレーション作業とコード(GitHubで公開)は、他のミュージシャンやエンジニアがヘンドリックスの信号処理テクニックを再現または拡張できるようにする可能性があります。 - この枠組みは、現代のアーティストが自らの機材をエンジニアリングされたシステムとして扱い、ヘンドリックスの手法に触発されて新しいペダルデザインを生み出すきっかけになるかもしれません。 **この影響が及ぼすもの(ユーザー/企業/業界)** - ギタリストやプロデューサーは、トーン形成により体系的なアプローチを採用し、身体運動コントロールを機材に組み込む可能性があります。 - ペダルメーカーは、文書化された回路図を参照してヘンドリックスの効果を模倣または改良した新モデルを開発できるでしょう。 - 音楽とエンジニアリングコミュニティは、パフォーマンス芸術と回路設計を融合させた具体的なケーススタディとして、この研究を活用できます。

2026/02/26 8:02

「最初のウェブサイト」

## Japanese Translation: 「オリジナルの要約は明確で包括的であり、主要なポイントを正確に反映しています。修正は必要ありません。」

2026/02/26 5:29

CLI で MCP を低価格化する方法

## Japanese Translation: ## Summary コマンドラインインターフェース(CLI)ツールは、マルチチャネルプログラム(MCP)エージェントと比較してトークン消費を劇的に削減します。セッション開始時には、CLI は約 300 トークンしか必要とせず、MCP はおよそ 15,500 トークンが必要です。各ツール呼び出しは、CLI で約 910 トークンかかり、MCP では 15,600 トークンになるため、90〜98 % の節約が得られます。10 個または 100 個のツールにスケーリングしても、節約率は高く(≈94 %と 92 %)維持されます。Anthropic の Tool Search はより大きなオーバーヘッドを伴い、検索インデックスをロードするだけで約 500 トークンが必要になり、要求時に完全な JSON スキーマを取得すると1回あたり約 3,530 トークンがかかります。これは CLI コストよりもはるかに高くなります。CLIHub はエージェント用の CLI ディレクトリと、MCP 定義を CLI 対応形式に変換するオープンソースコンバータを提供しています。これらの調査結果は、既存ツールを CLI 形式に移行または変換することでトークン使用量を大幅に削減し、API コストを低減し、レスポンス速度を向上させることができることを示唆しています。

**Show HN: Tree‑Sitter を Go に移植しました** Tree‑Sitter のパーサライブラリを C から Go に完全に移植し、使用できる状態になりました。 - **なぜ?** - Go プロジェクトとの統合が容易になります。 - C‑Go バインディングとその落とし穴を回避できます。 - **含まれる内容は?** - コア API 全般(パーサ作成、文法読み込み、構文木走査)。 - 元の C テストスイートに合わせた最小限のテストセット。 - **使い方** ```go import "github.com/yourrepo/tree-sitter-go" parser := treesitter.NewParser() parser.SetLanguage(treesitter.Go) root := parser.Parse(nil, sourceCode) ``` (詳細は README のサンプルをご覧ください。) - **パフォーマンス** - ベンチマークでは、ほとんどのワークロードで C バージョンに匹敵する速度を確認。 - Go の GC によりメモリ使用量がわずかに増加します。 - **ロードマップ** - 増分パース(incremental parsing)のサポート追加。 - 現在のサブセットを超える言語文法への拡張。 ぜひ試してみてください。問題があれば報告、あるいは貢献も歓迎します! | そっか~ニュース