aboutsummaryrefslogtreecommitdiff
path: root/docs/posts/introducing_tablespoon/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/posts/introducing_tablespoon/index.html')
-rw-r--r--docs/posts/introducing_tablespoon/index.html211
1 files changed, 211 insertions, 0 deletions
diff --git a/docs/posts/introducing_tablespoon/index.html b/docs/posts/introducing_tablespoon/index.html
new file mode 100644
index 0000000..a6f6ef2
--- /dev/null
+++ b/docs/posts/introducing_tablespoon/index.html
@@ -0,0 +1,211 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <link rel="stylesheet" href="/style.css">
5 <link rel="stylesheet" href="/syntax.css">
6 <meta charset="UTF-8">
7 <meta name="viewport" content="initial-scale=1">
8 <meta content="#ffffff" name="theme-color">
9 <meta name="HandheldFriendly" content="true">
10 <meta property="og:title" content="Introducing Tablespoon">
11 <meta property="og:type" content="website">
12 <meta property="og:description" content="a static site {for, by, about} me ">
13 <meta property="og:url" content="https://peppe.rs">
14 <link rel="icon" type="image/x-icon" href="/favicon.png">
15 <title>Introducing Tablespoon · peppe.rs</title>
16 <body>
17 <div class="posts">
18 <div class="post">
19 <a href="/" class="post-end-link">Home</a>
20 <span>/</span>
21 <a href="/posts" class="post-end-link">Posts</a>
22 <span>/</span>
23 <a class="post-end-link">Introducing Tablespoon</a>
24 <a class="stats post-end-link" href="https://git.peppe.rs/web/site/plain/posts/introducing_tablespoon.md
25">View Raw</a>
26 <div class="separator"></div>
27 <div class="date">
28 01/08 — 2024
29 <div class="stats">
30 <span class="stats-number">
31 72.33
32 </span>
33 <span class="stats-unit">cm</span>
34 &nbsp
35 <span class="stats-number">
36 4.5
37 </span>
38 <span class="stats-unit">min</span>
39 </div>
40 </div>
41 <h1>
42 Introducing Tablespoon
43 </h1>
44 <div class="post-text">
45 <p><a href="https://git.peppe.rs/languages/tbsp">tbsp</a> (tree-based
46source-processing language) is an awk-like language that operates on
47tree-sitter syntax trees. To motivate the need for such a program, we
48could begin by writing a markdown-to-html converter using
49<code>tbsp</code> and <a
50href="https://github.com/tree-sitter-grammars/tree-sitter-markdown">tree-sitter-md</a>.
51We need some markdown to begin with:</p>
52<pre><code># 1 heading
53
54content of first paragraph
55
56## 1.1 heading
57
58content of nested paragraph</code></pre>
59<p>For future reference, this markdown is parsed like so by
60tree-sitter-md (visualization generated by <a
61href="https://git.peppe.rs/cli/tree-viz">tree-viz</a>):</p>
62<pre><code>document
63| section
64| | atx_heading
65| | | atx_h1_marker &quot;#&quot;
66| | | heading_content inline &quot;1 heading&quot;
67| | paragraph
68| | | inline &quot;content of first paragraph&quot;
69| | section
70| | | atx_heading
71| | | | atx_h2_marker &quot;##&quot;
72| | | | heading_content inline &quot;1.1 heading&quot;
73| | | paragraph
74| | | | inline &quot;content of nested paragraph&quot;</code></pre>
75<p>Onto the converter itself. Every <code>tbsp</code> program is written
76as a collection of stanzas. Typically, we start with a stanza like
77so:</p>
78<pre><code>BEGIN {
79 int depth = 0;
80
81 print(&quot;&lt;html&gt;\n&quot;);
82 print(&quot;&lt;body&gt;\n&quot;);
83}</code></pre>
84<p>The stanza begins with a “pattern”, in this case, <code>BEGIN</code>,
85and is followed a block of code. This block specifically, is executed
86right at the beginning, before traversing the parse tree. In this
87stanza, we set a “depth” variable to keep track of nesting of markdown
88headers, and begin our html document by printing the
89<code>&lt;html&gt;</code> and <code>&lt;body&gt;</code> tags.</p>
90<p>We can follow this stanza with an <code>END</code> stanza, that is
91executed after the traversal:</p>
92<pre><code>END {
93 print(&quot;&lt;/body&gt;\n&quot;);
94 print(&quot;&lt;/html&gt;\n&quot;);
95}</code></pre>
96<p>In this stanza, we close off the tags we opened at the start of the
97document. We can move onto the interesting bits of the conversion
98now:</p>
99<pre><code>enter section {
100 depth += 1;
101}
102leave section {
103 depth -= 1;
104}</code></pre>
105<p>The above stanzas begin with <code>enter</code> and
106<code>leave</code> clauses, followed by the name of a tree-sitter node
107kind: <code>section</code>. The <code>section</code> identifier is
108visible in the tree-visualization above, it encompasses a
109markdown-section, and is created for every markdown header. To
110understand how <code>tbsp</code> executes above stanzas:</p>
111<pre><code>document ... depth = 0
112| section &lt;-------- enter section (1) ... depth = 1
113| | atx_heading
114| | | inline
115| | paragraph
116| | | inline
117| | section &lt;----- enter section (2) ... depth = 2
118| | | atx_heading
119| | | | inline
120| | | paragraph
121| | | | inline
122| | | &lt;----------- leave section (2) ... depth = 1
123| | &lt;-------------- leave section (1) ... depth = 0 </code></pre>
124<p>The following stanzas should be self-explanatory now:</p>
125<pre><code>enter atx_heading {
126 print(&quot;&lt;h&quot;);
127 print(depth);
128 print(&quot;&gt;&quot;);
129}
130leave atx_heading {
131 print(&quot;&lt;/h&quot;);
132 print(depth);
133 print(&quot;&gt;\n&quot;);
134}
135
136enter inline {
137 print(text(node));
138}</code></pre>
139<p>But an explanation is included nonetheless:</p>
140<pre><code>document ... depth = 0
141| section &lt;-------- enter section (1) ... depth = 1
142| | atx_heading &lt;- enter atx_heading ... print &quot;&lt;h1&gt;&quot;
143| | | inline &lt;--- enter inline ... print ..
144| | | &lt;----------- leave atx_heading ... print &quot;&lt;/h1&gt;&quot;
145| | paragraph
146| | | inline &lt;--- enter inline ... print ..
147| | section &lt;----- enter section (2) ... depth = 2
148| | | atx_heading enter atx_heading ... print &quot;&lt;h2&gt;&quot;
149| | | | inline &lt;- enter inline ... print ..
150| | | | &lt;-------- leave atx_heading ... print &quot;&lt;/h2&gt;&quot;
151| | | paragraph
152| | | | inline &lt;- enter inline ... print ..
153| | | &lt;----------- leave section (2) ... depth = 1
154| | &lt;-------------- leave section (1) ... depth = 0 </code></pre>
155<p>The <a
156href="https://git.peppe.rs/languages/tbsp/tree/examples">examples</a>
157directory contains a complete markdown-to-html converter, along with a
158few other motivating examples.</p>
159<h3 id="usage">Usage</h3>
160<p>The <code>tbsp</code> evaluator is written in rust, use cargo to
161build and run:</p>
162<pre><code>cargo build --release
163./target/release/tbsp --help</code></pre>
164<p><code>tbsp</code> requires three inputs:</p>
165<ul>
166<li>a <code>tbsp</code> program, referred to as “program file”</li>
167<li>a language</li>
168<li>an input file or some input text at stdin</li>
169</ul>
170<p>You can run the interpreter like so (this program prints an overview
171of a rust file):</p>
172<pre><code>$ ./target/release/tbsp \
173 -f./examples/code-overview/overview.tbsp \
174 -l rust \
175 src/main.rs
176module
177 └╴struct Cli
178 └╴trait Cli
179 └╴fn program
180 └╴fn language
181 └╴fn file
182 └╴fn try_consume_stdin
183 └╴fn main</code></pre>
184
185 </div>
186
187 <div class="intro">
188 Hi.
189 <div class="hot-links">
190 <a href="/index.xml" class="feed-button">Subscribe</a>
191 </div>
192 <p>I'm Akshay, programmer and pixel-artist.
193 I write <a href="https://git.peppe.rs">open-source stuff</a>.
194 I also design fonts:
195 <a href="https://git.peppe.rs/fonts/scientifica/about">scientifica</a>,
196 <a href="https://git.peppe.rs/fonts/curie/about">curie</a>.
197 </p>
198 <p>Reach out at [email protected].</p>
199 </div>
200
201 <a href="/" class="post-end-link">Home</a>
202 <span>/</span>
203 <a href="/posts" class="post-end-link">Posts</a>
204 <span>/</span>
205 <a class="post-end-link">Introducing Tablespoon</a>
206 <a class="stats post-end-link" href="https://git.peppe.rs/web/site/plain/posts/introducing_tablespoon.md
207">View Raw</a>
208 </div>
209 </div>
210 </body>
211</html>