aboutsummaryrefslogtreecommitdiff
path: root/docs/index.xml
diff options
context:
space:
mode:
Diffstat (limited to 'docs/index.xml')
-rw-r--r--docs/index.xml145
1 files changed, 145 insertions, 0 deletions
diff --git a/docs/index.xml b/docs/index.xml
index 9245aba..eec76ca 100644
--- a/docs/index.xml
+++ b/docs/index.xml
@@ -12,6 +12,151 @@
12 <language>en-us</language> 12 <language>en-us</language>
13 <copyright>Creative Commons BY-NC-SA 4.0</copyright> 13 <copyright>Creative Commons BY-NC-SA 4.0</copyright>
14 <item> 14 <item>
15<title>Introducing Tablespoon</title>
16<description>&lt;p&gt;&lt;a href="https://git.peppe.rs/languages/tbsp"&gt;tbsp&lt;/a&gt; (tree-based
17source-processing language) is an awk-like language that operates on
18tree-sitter syntax trees. To motivate the need for such a program, we
19could begin by writing a markdown-to-html converter using
20&lt;code&gt;tbsp&lt;/code&gt; and &lt;a
21href="https://github.com/tree-sitter-grammars/tree-sitter-markdown"&gt;tree-sitter-md&lt;/a&gt;.
22We need some markdown to begin with:&lt;/p&gt;
23&lt;pre&gt;&lt;code&gt;# 1 heading
24
25content of first paragraph
26
27## 1.1 heading
28
29content of nested paragraph&lt;/code&gt;&lt;/pre&gt;
30&lt;p&gt;For future reference, this markdown is parsed like so by
31tree-sitter-md (visualization generated by &lt;a
32href="https://git.peppe.rs/cli/tree-viz"&gt;tree-viz&lt;/a&gt;):&lt;/p&gt;
33&lt;pre&gt;&lt;code&gt;document
34| section
35| | atx_heading
36| | | atx_h1_marker &amp;quot;#&amp;quot;
37| | | heading_content inline &amp;quot;1 heading&amp;quot;
38| | paragraph
39| | | inline &amp;quot;content of first paragraph&amp;quot;
40| | section
41| | | atx_heading
42| | | | atx_h2_marker &amp;quot;##&amp;quot;
43| | | | heading_content inline &amp;quot;1.1 heading&amp;quot;
44| | | paragraph
45| | | | inline &amp;quot;content of nested paragraph&amp;quot;&lt;/code&gt;&lt;/pre&gt;
46&lt;p&gt;Onto the converter itself. Every &lt;code&gt;tbsp&lt;/code&gt; program is written
47as a collection of stanzas. Typically, we start with a stanza like
48so:&lt;/p&gt;
49&lt;pre&gt;&lt;code&gt;BEGIN {
50 int depth = 0;
51
52 print(&amp;quot;&amp;lt;html&amp;gt;\n&amp;quot;);
53 print(&amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;);
54}&lt;/code&gt;&lt;/pre&gt;
55&lt;p&gt;The stanza begins with a “pattern”, in this case, &lt;code&gt;BEGIN&lt;/code&gt;,
56and is followed a block of code. This block specifically, is executed
57right at the beginning, before traversing the parse tree. In this
58stanza, we set a “depth” variable to keep track of nesting of markdown
59headers, and begin our html document by printing the
60&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
61&lt;p&gt;We can follow this stanza with an &lt;code&gt;END&lt;/code&gt; stanza, that is
62executed after the traversal:&lt;/p&gt;
63&lt;pre&gt;&lt;code&gt;END {
64 print(&amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;);
65 print(&amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;);
66}&lt;/code&gt;&lt;/pre&gt;
67&lt;p&gt;In this stanza, we close off the tags we opened at the start of the
68document. We can move onto the interesting bits of the conversion
69now:&lt;/p&gt;
70&lt;pre&gt;&lt;code&gt;enter section {
71 depth += 1;
72}
73leave section {
74 depth -= 1;
75}&lt;/code&gt;&lt;/pre&gt;
76&lt;p&gt;The above stanzas begin with &lt;code&gt;enter&lt;/code&gt; and
77&lt;code&gt;leave&lt;/code&gt; clauses, followed by the name of a tree-sitter node
78kind: &lt;code&gt;section&lt;/code&gt;. The &lt;code&gt;section&lt;/code&gt; identifier is
79visible in the tree-visualization above, it encompasses a
80markdown-section, and is created for every markdown header. To
81understand how &lt;code&gt;tbsp&lt;/code&gt; executes above stanzas:&lt;/p&gt;
82&lt;pre&gt;&lt;code&gt;document ... depth = 0
83| section &amp;lt;-------- enter section (1) ... depth = 1
84| | atx_heading
85| | | inline
86| | paragraph
87| | | inline
88| | section &amp;lt;----- enter section (2) ... depth = 2
89| | | atx_heading
90| | | | inline
91| | | paragraph
92| | | | inline
93| | | &amp;lt;----------- leave section (2) ... depth = 1
94| | &amp;lt;-------------- leave section (1) ... depth = 0 &lt;/code&gt;&lt;/pre&gt;
95&lt;p&gt;The following stanzas should be self-explanatory now:&lt;/p&gt;
96&lt;pre&gt;&lt;code&gt;enter atx_heading {
97 print(&amp;quot;&amp;lt;h&amp;quot;);
98 print(depth);
99 print(&amp;quot;&amp;gt;&amp;quot;);
100}
101leave atx_heading {
102 print(&amp;quot;&amp;lt;/h&amp;quot;);
103 print(depth);
104 print(&amp;quot;&amp;gt;\n&amp;quot;);
105}
106
107enter inline {
108 print(text(node));
109}&lt;/code&gt;&lt;/pre&gt;
110&lt;p&gt;But an explanation is included nonetheless:&lt;/p&gt;
111&lt;pre&gt;&lt;code&gt;document ... depth = 0
112| section &amp;lt;-------- enter section (1) ... depth = 1
113| | atx_heading &amp;lt;- enter atx_heading ... print &amp;quot;&amp;lt;h1&amp;gt;&amp;quot;
114| | | inline &amp;lt;--- enter inline ... print ..
115| | | &amp;lt;----------- leave atx_heading ... print &amp;quot;&amp;lt;/h1&amp;gt;&amp;quot;
116| | paragraph
117| | | inline &amp;lt;--- enter inline ... print ..
118| | section &amp;lt;----- enter section (2) ... depth = 2
119| | | atx_heading enter atx_heading ... print &amp;quot;&amp;lt;h2&amp;gt;&amp;quot;
120| | | | inline &amp;lt;- enter inline ... print ..
121| | | | &amp;lt;-------- leave atx_heading ... print &amp;quot;&amp;lt;/h2&amp;gt;&amp;quot;
122| | | paragraph
123| | | | inline &amp;lt;- enter inline ... print ..
124| | | &amp;lt;----------- leave section (2) ... depth = 1
125| | &amp;lt;-------------- leave section (1) ... depth = 0 &lt;/code&gt;&lt;/pre&gt;
126&lt;p&gt;The &lt;a
127href="https://git.peppe.rs/languages/tbsp/tree/examples"&gt;examples&lt;/a&gt;
128directory contains a complete markdown-to-html converter, along with a
129few other motivating examples.&lt;/p&gt;
130&lt;h3 id="usage"&gt;Usage&lt;/h3&gt;
131&lt;p&gt;The &lt;code&gt;tbsp&lt;/code&gt; evaluator is written in rust, use cargo to
132build and run:&lt;/p&gt;
133&lt;pre&gt;&lt;code&gt;cargo build --release
134./target/release/tbsp --help&lt;/code&gt;&lt;/pre&gt;
135&lt;p&gt;&lt;code&gt;tbsp&lt;/code&gt; requires three inputs:&lt;/p&gt;
136&lt;ul&gt;
137&lt;li&gt;a &lt;code&gt;tbsp&lt;/code&gt; program, referred to as “program file”&lt;/li&gt;
138&lt;li&gt;a language&lt;/li&gt;
139&lt;li&gt;an input file or some input text at stdin&lt;/li&gt;
140&lt;/ul&gt;
141&lt;p&gt;You can run the interpreter like so (this program prints an overview
142of a rust file):&lt;/p&gt;
143&lt;pre&gt;&lt;code&gt;$ ./target/release/tbsp \
144 -f./examples/code-overview/overview.tbsp \
145 -l rust \
146 src/main.rs
147module
148 └╴struct Cli
149 └╴trait Cli
150 └╴fn program
151 └╴fn language
152 └╴fn file
153 └╴fn try_consume_stdin
154 └╴fn main&lt;/code&gt;&lt;/pre&gt;</description>
155<link>https://peppe.rs/posts/introducing_tablespoon/</link>
156<pubDate>Thu, 01 Aug 2024 19:18:00 +0000</pubDate>
157<guid>https://peppe.rs/posts/introducing_tablespoon/</guid>
158</item>
159<item>
15<title>Snip Snap</title> 160<title>Snip Snap</title>
16<description>&lt;p&gt;I regularly switch between exactly two things while working, a 161<description>&lt;p&gt;I regularly switch between exactly two things while working, a
17“current” and an “alternate” item; a lot of tools I use seem to support 162“current” and an “alternate” item; a lot of tools I use seem to support