Tbsp – treesitter-based source processing language
git.peppe.rs
git.peppe.rs
I’m currently using tree-sitter at work to build AST-based tools, as performance is amazing, even with huge codebases, but I’m finding it slightly frustrating to have to manually write recursive descent processors keyed by strings, with no compile time guarantees on the structure of the grammar.
This is compounded by the fact that grammars themselves don’t really follow any standard structure, some have named fields (presumably the ones created after GitHub contributed this feature), while others require hierarchical pattern matching.
I wish there existed a tool to consume a grammar and output a rust ADT that we can simply match on. This would at least save me from redundant error handling. I’d build one myself, but I’m that good at rust yet.
Is the pattern matching API not sufficiently high level? In my experience, it's a huge improvement over implementing visitors for everything.
https://tree-sitter.github.io/tree-sitter/using-parsers#patt...
I haven't gotten into it yet but it looks pretty neat, and it's an official tool.
I'm a big fan of semgrep letting me query ASTs, this feels like something in a similar space. Down with lines, up with everything being trees!
At work, we use it for enforcing a bunch of custom lint rules configured as a yaml file committed directly to our repo, entirely cloud-free.
(I may be overreading your comment as suggesting that these were reasons to use ast-grep over semgrep.)
I have used `ast-grep` to devise my own linters with crushing success.
Question (caveat: first export to treesitter and tools like this): Is there a reason the example demonstrates the use of depth as a variable instead of it being built in?
Nesting level of a particular "type" is general enough that it might be included OOTB. What you want to do with this might be generalizable - for example instead of
```
enter section {
depth += 1;
}
leave section {
depth -= 1;
}
enter atx_heading {
print("<h");
print(depth);
print(">");
}
leave atx_heading {
print("</h");
print(depth);
print(">\n");
}
```It could simply be:
```
enter atx_heading {
print("<h");
print(depth);
print(">");
}
leave atx_heading {
print("</h");
print(depth);
print(">\n");
}
```So depth is always of the nested levels of the same node type, but available out of the box. For markdown, it's headings, sections and lists come to mind - but I might be wrong.
In any event, this looks really well thought-out and now to checkout the other tools mentioned in the comments.....
Very different, but a very fine tool tool too.
In any case, in the non-software world, “RR” stands for railroad, as it does in the name of that tool. You can’t own a common two-letter abbreviation.
I ask because I wrote Combobulate [1], a structured editing and movement tool for Emacs using TS.
But some people did nice attempts like https://github.com/eatkins/tree-sitter-ebnf-generator that I also adapted and exposed it here https://mingodad.github.io/lua-wasm-playground/ to allow play with it online (select "Tree-sitter-ebnf-generator" from examples then click "Run" to see a "grammar.js" generated from the content in "Input Text (arg[1])").
Just yesterday I started some experiments in that direction, to visualize grammars, but now I can rather do something else ..
> "...it is not recommended to use this parser where correctness is important. The main goal for this parser is to provide syntactical information for syntax highlighting..."
There's also a separate block-level and inline parser, not sure how `tbsp` handles nested or multi-stage parsing.
[1]: https://github.com/tree-sitter-grammars/tree-sitter-markdown
> These stem from restricting a complex format such as markdown to the quite restricting tree-sitter parsing rules.
[1]: Outside of something like tree-sitter v2 with a much more complex grammar support. And frankly I personally don't think making more complex grammars in Javascript+C is a good way forward.
I wonder if the `enter|exit ...` syntax might be too limiting but for a lot of stuff it seems nice and easy to reason about. Easier than tree-sitter's own queries.
I think if you really wanted performance and whatnot, you might end up compiling the queries to another target and just reuse them.
I could see myself writing a lua DSL around compiling these kinds of queries `enter/exit` stanzas or an SQL one too.
We always say naming things is one of the hard parts of programming. They avoided the default option of something like tawk.
Here is the new account and doc for tbsp below.
they define themselves as non linear patter matching pretty niche and unique way to program and i enjoyed playing with thier code
thanks for posting very nice
I joke, really interesting project, props to the team