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