Skip to content

msuozzo/bonsai

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bonsai

Pure-Go tree-sitter parsers. Each grammar is compiled to WebAssembly with a pinned toolchain and translated to Go by wasm2go, then published as its own Go module: no cgo, no shared libraries, nothing fetched at runtime.

Use

go get github.com/msuozzo/bonsai/bonsai-python
import bonsaipython "github.com/msuozzo/bonsai/bonsai-python"

src, _ := os.ReadFile("example.py")

p := bonsaipython.NewParser()
root, err := p.Parse(src)
if err != nil {
	return err
}
for fn := range root.Find("function_definition") {
	name := fn.ChildByField("name")
	fmt.Printf("def %s @ line %d\n", name.Text(src), fn.StartPoint.Row+1)
}

Import only the languages you need: every cost (download, compile, binary size) scales with the modules you actually import. A Parser is not goroutine-safe. Pool one per goroutine and reuse it across files. Instantiation is the expensive part.

Languages

module grammar pinned module zip binary cost¹
bonsai-bash tree-sitter-bash v0.25.1 390 KB +2.5 MB
bonsai-dockerfile tree-sitter-dockerfile v0.2.0 100 KB +0.3 MB
bonsai-go tree-sitter-go v0.25.0 130 KB +0.4 MB
bonsai-gotemplate tree-sitter-go-template master 100 KB +0.3 MB
bonsai-groovy tree-sitter-groovy initial 250 KB +1.6 MB
bonsai-markdown tree-sitter-markdown (block + inline) v0.5.3 430 KB +2.2 MB
bonsai-python tree-sitter-python v0.25.0 160 KB +0.6 MB
bonsai-terraform tree-sitter-hcl (terraform dialect) v1.2.0 110 KB +0.3 MB
bonsai-yaml tree-sitter-yaml v0.7.2 130 KB +0.5 MB

¹ stripped-binary delta (-trimpath -ldflags='-s -w') over a 1.6 mb baseline that imports no grammar module. the bonsai-markdown row covers the combined block + inline parsers via NewFullParser, each individual grammar accounting for roughly half.

Versioning

Language modules encode the upstream grammar version in the tag's minor number and reserve the patch for re-releases (toolchain or runtime bumps at the same grammar):

bonsai-<lang>/v0.<encoded>.<respin>
encoded = major·10000 + minor·100 + patch  (of the upstream grammar tag)

tree-sitter-python v0.25.0          → bonsai-python/v0.2500.0
  …rebuilt with a newer toolchain   → bonsai-python/v0.2500.1
tree-sitter-python v0.25.1          → bonsai-python/v0.2501.0

(Mirroring upstream tags verbatim was rejected: a re-release at the same grammar version would have to squat on upstream's next patch number.) Grammars without a semver upstream tag use encoded = 0 until upstream cuts a release. The encoding exists for ordering, not parsing: the exact upstream pin is always in the module's build.env and meta_gen.go header.

The root module (github.com/msuozzo/bonsai, the runtime) versions independently as plain SemVer. Each language module pins the root version it was generated against. A runtime-ABI change means regenerating and re-releasing every language (CI enforces the regeneration half).

Releases are cut by tagging the root, replacing each language go.mod's replace directive with a require of that tag, then tagging each language module. No versions are tagged yet.

Regenerating

Each language module's *_gen.* files are produced hermetically in Docker from the pins in bonsai-<lang>/build.env:

go generate ./bonsai-python      # or: build/regen.sh python | all

CI rebuilds every language in a parallel job matrix on each PR and fails if any generated byte differs from what's checked in.

Note: Regeneration builds ncruces/wasm2go pinned by commit in Dockerfile.builder: the pass that keeps large lexers within go/parser's nesting limits (ncruces/wasm2go#42) landed after the latest tagged release. The pin moves to a tagged release once one contains it.

Licensing

The wasm→Go translation is mechanical: upstream authors retain copyright over the code compiled into each module. Each generated module is a derivative of the tree-sitter runtime and of its grammar (both MIT), so their license texts ship inside the module (LICENSE.tree-sitter, LICENSE.grammar) and are additionally embedded into consuming binaries via licenses_gen.go (LicenseTreeSitter/LicenseGrammar), keeping the required notices attached to compiled redistributions.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors