From 9828c78d95f2195cd8e1db04887072cd5f48005b Mon Sep 17 00:00:00 2001 From: Akshay Date: Thu, 1 Aug 2024 20:24:57 +0100 Subject: new post: tablespoon --- docs/index.html | 24 +-- docs/index.xml | 145 ++++++++++++++++++ docs/posts/index.html | 17 +++ docs/posts/introducing_tablespoon/index.html | 211 +++++++++++++++++++++++++++ docs/style.css | 7 +- 5 files changed, 390 insertions(+), 14 deletions(-) create mode 100644 docs/posts/introducing_tablespoon/index.html (limited to 'docs') diff --git a/docs/index.html b/docs/index.html index d42ab2b..2d9b619 100644 --- a/docs/index.html +++ b/docs/index.html @@ -39,15 +39,15 @@
- 29/05 — 2024 + 01/08 — 2024
- - Snip Snap + + Introducing Tablespoon - 2.1 + 4.5 min @@ -56,15 +56,15 @@
- 18/06 — 2023 + 29/05 — 2024
- - Plain Text Journaling + + Snip Snap - 8.9 + 2.1 min @@ -73,15 +73,15 @@
- 03/09 — 2022 + 18/06 — 2023
- - Curing A Case Of Git-UX + + Plain Text Journaling - 9.6 + 8.9 min 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 @@ en-us Creative Commons BY-NC-SA 4.0 +Introducing Tablespoon +<p><a href="https://git.peppe.rs/languages/tbsp">tbsp</a> (tree-based +source-processing language) is an awk-like language that operates on +tree-sitter syntax trees. To motivate the need for such a program, we +could begin by writing a markdown-to-html converter using +<code>tbsp</code> and <a +href="https://github.com/tree-sitter-grammars/tree-sitter-markdown">tree-sitter-md</a>. +We need some markdown to begin with:</p> +<pre><code># 1 heading + +content of first paragraph + +## 1.1 heading + +content of nested paragraph</code></pre> +<p>For future reference, this markdown is parsed like so by +tree-sitter-md (visualization generated by <a +href="https://git.peppe.rs/cli/tree-viz">tree-viz</a>):</p> +<pre><code>document +| section +| | atx_heading +| | | atx_h1_marker &quot;#&quot; +| | | heading_content inline &quot;1 heading&quot; +| | paragraph +| | | inline &quot;content of first paragraph&quot; +| | section +| | | atx_heading +| | | | atx_h2_marker &quot;##&quot; +| | | | heading_content inline &quot;1.1 heading&quot; +| | | paragraph +| | | | inline &quot;content of nested paragraph&quot;</code></pre> +<p>Onto the converter itself. Every <code>tbsp</code> program is written +as a collection of stanzas. Typically, we start with a stanza like +so:</p> +<pre><code>BEGIN { + int depth = 0; + + print(&quot;&lt;html&gt;\n&quot;); + print(&quot;&lt;body&gt;\n&quot;); +}</code></pre> +<p>The stanza begins with a “pattern”, in this case, <code>BEGIN</code>, +and is followed a block of code. This block specifically, is executed +right at the beginning, before traversing the parse tree. In this +stanza, we set a “depth” variable to keep track of nesting of markdown +headers, and begin our html document by printing the +<code>&lt;html&gt;</code> and <code>&lt;body&gt;</code> tags.</p> +<p>We can follow this stanza with an <code>END</code> stanza, that is +executed after the traversal:</p> +<pre><code>END { + print(&quot;&lt;/body&gt;\n&quot;); + print(&quot;&lt;/html&gt;\n&quot;); +}</code></pre> +<p>In this stanza, we close off the tags we opened at the start of the +document. We can move onto the interesting bits of the conversion +now:</p> +<pre><code>enter section { + depth += 1; +} +leave section { + depth -= 1; +}</code></pre> +<p>The above stanzas begin with <code>enter</code> and +<code>leave</code> clauses, followed by the name of a tree-sitter node +kind: <code>section</code>. The <code>section</code> identifier is +visible in the tree-visualization above, it encompasses a +markdown-section, and is created for every markdown header. To +understand how <code>tbsp</code> executes above stanzas:</p> +<pre><code>document ... depth = 0 +| section &lt;-------- enter section (1) ... depth = 1 +| | atx_heading +| | | inline +| | paragraph +| | | inline +| | section &lt;----- enter section (2) ... depth = 2 +| | | atx_heading +| | | | inline +| | | paragraph +| | | | inline +| | | &lt;----------- leave section (2) ... depth = 1 +| | &lt;-------------- leave section (1) ... depth = 0 </code></pre> +<p>The following stanzas should be self-explanatory now:</p> +<pre><code>enter atx_heading { + print(&quot;&lt;h&quot;); + print(depth); + print(&quot;&gt;&quot;); +} +leave atx_heading { + print(&quot;&lt;/h&quot;); + print(depth); + print(&quot;&gt;\n&quot;); +} + +enter inline { + print(text(node)); +}</code></pre> +<p>But an explanation is included nonetheless:</p> +<pre><code>document ... depth = 0 +| section &lt;-------- enter section (1) ... depth = 1 +| | atx_heading &lt;- enter atx_heading ... print &quot;&lt;h1&gt;&quot; +| | | inline &lt;--- enter inline ... print .. +| | | &lt;----------- leave atx_heading ... print &quot;&lt;/h1&gt;&quot; +| | paragraph +| | | inline &lt;--- enter inline ... print .. +| | section &lt;----- enter section (2) ... depth = 2 +| | | atx_heading enter atx_heading ... print &quot;&lt;h2&gt;&quot; +| | | | inline &lt;- enter inline ... print .. +| | | | &lt;-------- leave atx_heading ... print &quot;&lt;/h2&gt;&quot; +| | | paragraph +| | | | inline &lt;- enter inline ... print .. +| | | &lt;----------- leave section (2) ... depth = 1 +| | &lt;-------------- leave section (1) ... depth = 0 </code></pre> +<p>The <a +href="https://git.peppe.rs/languages/tbsp/tree/examples">examples</a> +directory contains a complete markdown-to-html converter, along with a +few other motivating examples.</p> +<h3 id="usage">Usage</h3> +<p>The <code>tbsp</code> evaluator is written in rust, use cargo to +build and run:</p> +<pre><code>cargo build --release +./target/release/tbsp --help</code></pre> +<p><code>tbsp</code> requires three inputs:</p> +<ul> +<li>a <code>tbsp</code> program, referred to as “program file”</li> +<li>a language</li> +<li>an input file or some input text at stdin</li> +</ul> +<p>You can run the interpreter like so (this program prints an overview +of a rust file):</p> +<pre><code>$ ./target/release/tbsp \ + -f./examples/code-overview/overview.tbsp \ + -l rust \ + src/main.rs +module + └╴struct Cli + └╴trait Cli + └╴fn program + └╴fn language + └╴fn file + └╴fn try_consume_stdin + └╴fn main</code></pre> +https://peppe.rs/posts/introducing_tablespoon/ +Thu, 01 Aug 2024 19:18:00 +0000 +https://peppe.rs/posts/introducing_tablespoon/ + + Snip Snap <p>I regularly switch between exactly two things while working, a “current” and an “alternate” item; a lot of tools I use seem to support diff --git a/docs/posts/index.html b/docs/posts/index.html index ca9a3ac..a8d321c 100644 --- a/docs/posts/index.html +++ b/docs/posts/index.html @@ -24,6 +24,23 @@
+ + + + +
+
+ 01/08 — 2024 +
+ + Introducing Tablespoon + +
+ + 4.5 + + min +
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 @@ + + + + + + + + + + + + + + + Introducing Tablespoon · peppe.rs + +
+
+ Home + / + Posts + / + Introducing Tablespoon + View Raw +
+
+ 01/08 — 2024 +
+ + 72.33 + + cm +   + + 4.5 + + min +
+
+

+ Introducing Tablespoon +

+
+

tbsp (tree-based +source-processing language) is an awk-like language that operates on +tree-sitter syntax trees. To motivate the need for such a program, we +could begin by writing a markdown-to-html converter using +tbsp and tree-sitter-md. +We need some markdown to begin with:

+
# 1 heading
+
+content of first paragraph
+
+## 1.1 heading
+
+content of nested paragraph
+

For future reference, this markdown is parsed like so by +tree-sitter-md (visualization generated by tree-viz):

+
document
+|  section
+|  |  atx_heading
+|  |  |  atx_h1_marker "#"
+|  |  |  heading_content inline "1 heading"
+|  |  paragraph
+|  |  |  inline "content of first paragraph"
+|  |  section
+|  |  |  atx_heading
+|  |  |  |  atx_h2_marker "##"
+|  |  |  |  heading_content inline "1.1 heading"
+|  |  |  paragraph
+|  |  |  |  inline "content of nested paragraph"
+

Onto the converter itself. Every tbsp program is written +as a collection of stanzas. Typically, we start with a stanza like +so:

+
BEGIN {
+    int depth = 0;
+
+    print("<html>\n");
+    print("<body>\n");
+}
+

The stanza begins with a “pattern”, in this case, BEGIN, +and is followed a block of code. This block specifically, is executed +right at the beginning, before traversing the parse tree. In this +stanza, we set a “depth” variable to keep track of nesting of markdown +headers, and begin our html document by printing the +<html> and <body> tags.

+

We can follow this stanza with an END stanza, that is +executed after the traversal:

+
END {
+    print("</body>\n");
+    print("</html>\n");
+}
+

In this stanza, we close off the tags we opened at the start of the +document. We can move onto the interesting bits of the conversion +now:

+
enter section {
+    depth += 1;
+}
+leave section {
+    depth -= 1;
+}
+

The above stanzas begin with enter and +leave clauses, followed by the name of a tree-sitter node +kind: section. The section identifier is +visible in the tree-visualization above, it encompasses a +markdown-section, and is created for every markdown header. To +understand how tbsp executes above stanzas:

+
document                                 ...  depth = 0 
+|  section <-------- enter section (1)   ...  depth = 1 
+|  |  atx_heading
+|  |  |  inline
+|  |  paragraph
+|  |  |  inline
+|  |  section <----- enter section (2)   ...  depth = 2 
+|  |  |  atx_heading
+|  |  |  | inline
+|  |  |  paragraph
+|  |  |  | inline
+|  |  | <----------- leave section (2)   ...  depth = 1 
+|  | <-------------- leave section (1)   ...  depth = 0 
+

The following stanzas should be self-explanatory now:

+
enter atx_heading {
+    print("<h");
+    print(depth);
+    print(">");
+}
+leave atx_heading {
+    print("</h");
+    print(depth);
+    print(">\n");
+}
+
+enter inline {
+    print(text(node));
+}
+

But an explanation is included nonetheless:

+
document                                 ...  depth = 0 
+|  section <-------- enter section (1)   ...  depth = 1 
+|  |  atx_heading <- enter atx_heading   ...  print "<h1>"
+|  |  |  inline <--- enter inline        ...  print ..
+|  |  | <----------- leave atx_heading   ...  print "</h1>"
+|  |  paragraph
+|  |  |  inline <--- enter inline        ...  print ..
+|  |  section <----- enter section (2)   ...  depth = 2 
+|  |  |  atx_heading enter atx_heading   ...  print "<h2>"
+|  |  |  | inline <- enter inline        ...  print ..
+|  |  |  | <-------- leave atx_heading   ...  print "</h2>"
+|  |  |  paragraph
+|  |  |  | inline <- enter inline        ...  print ..
+|  |  | <----------- leave section (2)   ...  depth = 1 
+|  | <-------------- leave section (1)   ...  depth = 0 
+

The examples +directory contains a complete markdown-to-html converter, along with a +few other motivating examples.

+

Usage

+

The tbsp evaluator is written in rust, use cargo to +build and run:

+
cargo build --release
+./target/release/tbsp --help
+

tbsp requires three inputs:

+
    +
  • a tbsp program, referred to as “program file”
  • +
  • a language
  • +
  • an input file or some input text at stdin
  • +
+

You can run the interpreter like so (this program prints an overview +of a rust file):

+
$ ./target/release/tbsp \
+      -f./examples/code-overview/overview.tbsp \
+      -l rust \
+      src/main.rs
+module
+   └╴struct Cli
+   └╴trait Cli
+      └╴fn program
+      └╴fn language
+      └╴fn file
+   └╴fn try_consume_stdin
+   └╴fn main
+ +
+ +
+ Hi. + +

I'm Akshay, programmer and pixel-artist. + I write open-source stuff. + I also design fonts: + scientifica, + curie. +

+

Reach out at oppili@irc.rizon.net.

+
+ + Home + / + Posts + / + Introducing Tablespoon + View Raw +
+
+ + diff --git a/docs/style.css b/docs/style.css index d4a8391..04f78a8 100644 --- a/docs/style.css +++ b/docs/style.css @@ -52,10 +52,13 @@ div.hot-links { } } -body { font-family: 'Inter', sans-serif; } +body { + font-family: 'Inter', sans-serif; + font-feature-settings: 'liga' 1, 'calt' 1; /* fix for Chrome */ +} @supports (font-variation-settings: normal) { body { - font-family: 'Inter var', sans-serif; + font-family: 'InterVariable', sans-serif; font-feature-settings: 'ss01' 1, 'kern' 1, 'liga' 1, 'cv05' 1, 'tnum' 1; } } -- cgit v1.2.3