summaryrefslogtreecommitdiff
path: root/drafts
diff options
context:
space:
mode:
authorBrandon C. Irizarry <brandon.irizarry@gmail.com>2026-02-26 19:37:01 -0500
committerBrandon C. Irizarry <brandon.irizarry@gmail.com>2026-02-26 19:37:01 -0500
commit204676006c9787b2d5db4512105741a6c1a61a8d (patch)
tree21b5b8b69b2a47c38bc0994790c20bfd521b3839 /drafts
Track blog
Diffstat (limited to 'drafts')
-rw-r--r--drafts/posts/apple-time.md21
-rw-r--r--drafts/posts/orange.md6
-rw-r--r--drafts/posts/smoothing-over-more-markdown-pain-points.md85
-rw-r--r--drafts/posts/understanding-pratt-parsing.md170
-rw-r--r--drafts/posts/writing-my-blog-with-eleventy.md104
5 files changed, 386 insertions, 0 deletions
diff --git a/drafts/posts/apple-time.md b/drafts/posts/apple-time.md
new file mode 100644
index 0000000..e012fc5
--- /dev/null
+++ b/drafts/posts/apple-time.md
@@ -0,0 +1,21 @@
++++
+title = "My first post"
+summary = "Stub post for buildablog"
++++
+
+# Roses are red
+
+Violets are blue, etc.
+<br>
+```go
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hello world!")
+}
+```
+<br>
+
+[This is a link](https://example.com)
diff --git a/drafts/posts/orange.md b/drafts/posts/orange.md
new file mode 100644
index 0000000..5890577
--- /dev/null
+++ b/drafts/posts/orange.md
@@ -0,0 +1,6 @@
++++
+title = "My first post"
+summary = "Stub post for buildablog"
++++
+
+# A new post right away
diff --git a/drafts/posts/smoothing-over-more-markdown-pain-points.md b/drafts/posts/smoothing-over-more-markdown-pain-points.md
new file mode 100644
index 0000000..ab87edb
--- /dev/null
+++ b/drafts/posts/smoothing-over-more-markdown-pain-points.md
@@ -0,0 +1,85 @@
++++
+title = "Smoothing Over More Markdown Pain Points"
+tags = ["blogging", "emacs"]
+date = 2025-12-05
+
+summary = """
+
+A post I had written about a small Elisp helper library I wrote for \
+generating a table of contents for a Markdown file.
+
+"""
+
++++
+
+# Table of Contents
+
++ [I Couldn't Keep It Together](#i-couldn't-keep-it-together)
++ [Elisp For The Win](#elisp-for-the-win)
++ [Yet Another Yasnippet Testimonial](#yet-another-yasnippet-testimonial)
++ [Now I Can Keep It Together!](#now-i-can-keep-it-together!)
+
+
+<a id="i-couldn't-keep-it-together"></a>
+# I Couldn't Keep It Together
+
+As I go about editing these blogs as Markdown buffers inside Emacs,
+I've been running into a snag of sorts. Previously, I had been
+exporting Org to Markdown one way or another. I observed how the
+Markdown output inserts an anchor tag above a given section as a way
+to link to it from the table of contents. I decided to continue this
+practice in my now hand-wrought Markdown. However, manually keeping
+the table of contents in sync with changes in the outlining of the
+content itself—adding and removing sections, renaming sections, and so
+on—is a pain. And so I came up with a way to sync the two, using
+Emacs Lisp. Emacs Lisp, or Elisp for short, is the Emacs editor's
+extension language: the language you use to write Emacs plugins.
+
+<a id="elisp-for-the-win"></a>
+# Elisp For The Win
+[Having written](https://brandonirizarry.xyz/blog/writing_my_blog_with_eleventy/#introduction) about my zany Elisp-based Java build system made
+me recall those times: I could once again rise to the challenge, and
+solve this new problem with Elisp. That's exactly what I did. I wrote
+two functions, `bcimd-generate-toc` and `bcimd-remove-toc`. The first
+one regenerates the table of contents based on the current set of
+level-1 headings. The second one erases the existing table of
+contents, along with the connected anchor tags. It's used by the first
+function to start out with a clean slate before defining the new table
+of contents.
+
+I decided to collect these functions into an installable package. It's
+currently available through Emacs' version-control installation
+mechanisms (for example, `package-vc-install`.) See the [project
+README](https://github.com/BrandonIrizarry/bcimd) for more details.
+
+I find Emacs' VC-based package installation facilities extremely
+convenient for writing my own bespoke stuff which I otherwise have to
+manage locally. I store it remotely, and install it as an *official*
+package, much like how Go packages work. In this way, I can even share
+my work with the community.
+
+<a id="yet-another-yasnippet-testimonial"></a>
+# Yet Another Yasnippet Testimonial
+
+I also decided to go the extra mile and use a [Yasnippet](Yasnippet) snippet
+that generates some stock front matter. In particular, the title of a
+given blog post is ripped directly from the name of the file itself,
+which first undergoes some on-the-fly formatting. I got this idea from
+[another blog](https://weblog.masukomi.org/2024/07/19/using-org-mode-with-hugo/) where the author runs with the whole Yasnippet idea
+to set up her `ox-hugo` front matter. In fact, this is what turned me
+on to the idea of Yasnippet as a useful tool in general; that is, it
+isn't just a lazy man's way of inserting a for-loop into source code.
+
+<a id="now-i-can-keep-it-together!"></a>
+# Now I Can Keep It Together!
+
+I now use table-of-contents regeneration frequently: writing the
+package was a worthwhile investment of time.The only minor hiccup is
+that I have to remember to leave two spaces in between headers, so
+that the anchor tag doesn't eliminate all whitespace between sections,
+an effect which looks aesthetically jarring. I may address this in the
+future, but I first need to see how this package interacts with, for
+example, level-2 headers. Other ideas include running
+table-of-contents generation as an `after-save-hook`, and eventually
+writing a full-blown minor-mode. But for now, I'm taking it easy on
+this project: I still have to work on other things.
diff --git a/drafts/posts/understanding-pratt-parsing.md b/drafts/posts/understanding-pratt-parsing.md
new file mode 100644
index 0000000..4c058fe
--- /dev/null
+++ b/drafts/posts/understanding-pratt-parsing.md
@@ -0,0 +1,170 @@
++++
+title = "Understanding Pratt Parsing"
+tags = ["programming languages"]
+date = 2025-12-02
+
+summary = """
+
+A post I had written about Pratt parsing, in the context of a \
+programming language I was designing at the time.
+
+"""
+
++++
+
+# Table of Contents
+
++ [Introduction](#introduction)
++ ["It's like a burrito"](#its-like-a-burrito)
++ [Down To Brass Tacks](#down-to-brass-tacks)
++ [Wanting More](#wanting-more)
+
+<a id="introduction"></a>
+
+# Introduction
+
+I've forgotten how I came across Pratt parsing specifically. I had
+been working on an interpreter for a programming language based on the
+one loosely described in Greg Michaelson's *An Introduction to
+Functional Programming Through Lambda Calculus*. I had managed to
+implement simple arithmetic, and even extended the basic lambda
+calculus spec with assignment expressions (a feat which I was very
+proud of.)
+
+However, some parts of my implementation felt a bit hacky (for
+example, how I had implemented `letrec`), and my implementation of
+lazy evaluation, while mostly complete, ultimately turned out to be
+buggy.
+
+At first, I decided to rewrite the project from scratch. One major
+guiding factor was to narrow the scope of the project, borrowing some
+advice from [Zed Shaw](https://learncodethehardway.com/blog/32-very-deep-not-boring-beginner-projects/). I got around to writing a new tokenizer,
+and then I was on to writing the parser. My initial parser used the
+recursive descent technique, taking advantage of the simplified lambda
+calculus grammar used in Michaelson's text (for example, parentheses
+are always used for application terms there.)
+
+This time though, I wanted to try something different. And so,
+rummaging through the internets, I stumbled across Pratt parsing.
+
+<a id="its-like-a-burrito"></a>
+
+# "It's like a burrito"
+
+Understanding Pratt parsing ended up being much harder than I
+expected. I ended up searching through a bunch of examples online:
+
+1. [Alex Kladov's](https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html) Rust-based tutorial.
+2. [Eli Bendersky's](https://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing) Python-based tutorial.
+3. Bob Nystrom's [intro](https://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/) to the subject, as well as the relevant
+ chapter in his [Crafting Interpreters](https://craftinginterpreters.com/compiling-expressions.html).
+4. Vaughan Pratt's [original paper](https://tdop.github.io/). Shout-out to the legend who
+ put this up as a GitHub Pages site!
+5. Douglas Crockford's celebrated [article](https://crockford.com/javascript/tdop/tdop.html) on the subject deserves
+ honorable mention, though my JavaScript is currently rusty and so I
+ didn't look into it in any depth.
+
+Alex Kladov in his post calls Pratt parsing the "monad tutorial of
+syntactic analysis". As I had recently become familiar with the
+concept of "monad" in a [philosophical](https://en.wikipedia.org/wiki/Monad_(philosophy)) sense, I aksed ChatGPT
+where the reference comes from: it turns out that it's an inside joke
+involving *Haskell* monads. I'm not an expert, but my readings have
+given me enough of an inkling to see the connection: Pratt parsing
+isn't a discrete "thing" with exactly one shape: it's more of a
+technique, if you will—a design pattern—which can assume various
+manifestations.
+
+A good example of this is iteration, because we all recognize it when
+we see it, even when we don't know the language—but no one syntactic
+construction sufficiently defines it. For-loops, while-loops, Python
+generator functions, and [optimized tail-recursive functions](https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/full-text/book/book-Z-H-11.html#%_sec_1.2.1 ) all
+count as iteration.
+
+After struggling for some time, I finally managed to distill the
+essence of the algorithm, which I present here as pseudocode:
+
+```
+parse(level):
+ t ← next(stream)
+ acc ← nud_dispatch(t)
+
+ while level < precedence(peek(stream)):
+ t ← next(stream)
+ acc ← led_dispatch(t, acc)
+
+ return acc
+```
+
+Unwrapping what this does exactly is a surprisingly nuanced task,
+precisely because the algorithm is more about technique than
+structure. Because of this, I won't pretend to be up to the task
+here. Nevertheless, a brief synopsis is warranted.
+
+There is a global `stream` of tokens, such that `next(stream)`
+consumes and returns the next token, and `peek(stream)` returns the
+next token without consuming it. The function `nud_dispatch`
+interprets `t` as a *null denotation*, or "nud" for short, and
+initializes `acc`. The function `led_dispatch` interprets `t` as a
+*left denotation*, or "led" for short. It accumulates a value into
+`acc` using the existing value of `acc` (hence the choice of name.)
+Both dispatch functions call `parse` recursively in all but the most
+trivial cases.
+
+When `peek`ing the stream reveals a token with higher precedence than
+the current `level`, the while loop exits and `acc` is returned.
+
+The algorithm is initialized by calling `parse(0)`.
+
+<a id="down-to-brass-tacks"></a>
+
+# Down To Brass Tacks
+
+My approach was to take Eli Bendersky's full source code at the bottom
+of his post, and start chiseling away at it. What I ended up with was
+the same simple arithmetic calculator, only with a different
+architecture: I moved away from Eli's object-oriented approach towards
+something closer to the formulation given in the previous section.
+
+In the end, I was amazed at how simple and robust the actual
+implementation turned out to be! I feel that what I came up with (at
+this stage, anyway) is arguably simpler than even many of the examples
+I initially came across: for example, it isn't necessary to add space
+between precedence levels (10, 20, etc.), since you can use an enum to
+take care of any ordering needed. Also, using even and odd precedence
+levels (for handling right associativity) is unnecessary. For example,
+say you have precedence levels `MULTIPLICATION = 2` and
+`EXPONENTIATION = 3`. The algorithm cleverly avoids clashing
+`EXPONENTIATION-1` with `MULTIPLICATION` when enforcing right
+associativity for exponentiation. I found this to be one of the more
+remarkable aspects of the algorithm.
+
+<a id="wanting-more"></a>
+
+# Wanting More
+
+To be fair, my calculator app technically doesn't parse arithmetic
+expressions: it evaluates them wholesale. This is OK: instead of
+accumulating an AST, I'm accumulating an arithmetic result.
+
+Because of how compelling the calculator app turned out to be, I
+decided to stop work on the lambda calculus project, and instead work
+on expanding the calculator into a full-blown programming language,
+albeit a simple one. I've already made progress in this direction: in
+addition to arithmetic (including trig functions!), the application
+currently supports variable assignment.
+
+Ideally, I'd like something with
+<br></br>
+
++ Booleans
++ Conditionals
++ Loops
++ Functions
++ Proper lexical scoping, even for conditional and loop blocks
+<br></br>
+I'll see how many of these I manage.
+
+
+
+
+
diff --git a/drafts/posts/writing-my-blog-with-eleventy.md b/drafts/posts/writing-my-blog-with-eleventy.md
new file mode 100644
index 0000000..c822446
--- /dev/null
+++ b/drafts/posts/writing-my-blog-with-eleventy.md
@@ -0,0 +1,104 @@
++++
+title = "Writing My Blog With Eleventy"
+tags = ["blogging"]
+date = 2025-12-03
+
+summary = """
+
+This is a reproduction of a post I had on my old blog, which I've \
+since migrated to a custom engine.
+
+"""
+
++++
+
+# Table of Contents
+
++ [Introduction](#introduction)
++ [Hugo](#hugo)
++ [Eleventy: The Soup Actually Tastes Good](#eleventy:-the-soup-actually-tastes-good)
++ [Painless Deployment](#painless-deployment)
++ [Conclusion](#conclusion)
+
+
+<a id="introduction"></a>
+# Introduction
+
+This is *at least* my third time trying to start a blog.
+
+First, I experimented with using Org Mode's HTML exporting feature to
+create posts; unfortunately, that didn't get me far, though there are
+some [interesting attempts](https://one.tonyaldon.com/) by others to this end. I might've
+published this material at some point, but at any rate it didn't stay
+up long. An early topic from this time include a post about a [Java
+build system](https://github.com/BrandonIrizarry/Hydraulic-Make) I once wrote that scanned a `.java` file for its
+dependencies (defined by things like package imports and code syntax),
+so that those would get passed into `javac` along with the target
+file.
+
+<a id="hugo"></a>
+# Hugo
+I then started writing a blog using Hugo. Hugo was my first encounter
+with an SSG. Because of this, I was a bit impatient with Hugo, and hit
+a wall every time I came across any sort of complexity. I also got
+frustrated with how themes never follow a consistent template; each
+does something different, with different elements, and so each one
+effectively has different rules. In the end, I published a blog post
+or two on GitHub pages using this setup. It was passable, but in the
+end configuring it still felt wonky and cargo-culted.
+
+Another reason for why I didn't have success with Hugo was my use of
+`ox-hugo`. It's a fun package, and you can tell the author put a *lot*
+of love into it. However, using Org Mode as a middleman between you
+and Hugo obfuscates the nature of Hugo, something I'm realizing now as
+I go deeper into using Eleventy.
+
+
+<a id="eleventy:-the-soup-actually-tastes-good"></a>
+# Eleventy: The Soup Actually Tastes Good
+
+I went ahead and did a little bit of "shopping" for SSGs. I ran into
+[Eleventy](https://www.11ty.dev). I watched the author's [intro video](https://www.youtube.com/watch?v=kzf9A9tkkl4), and
+immediately took a liking to it. After a few false starts, I cloned
+their [official starter project](https://github.com/11ty/eleventy-base-blog), tweaked it here and there, and
+the rest is what you're currently looking at.
+
+A huge shift in my thinking which made the leap from Hugo to Eleventy
+possible occurred when I learned to stop worrying and love the
+Markdown.
+
+I used to think of Markdown as an icky, second-rate version of Org
+Mode. Then, I eventually got the hang of writing Markdown using Emacs'
+`markdown-mode` package, which is a [masterpiece](https://jblevins.org/projects/markdown-mode/) of a plugin: it
+makes the experience of writing Markdown rival that of using Org, and
+smoothes out a lot of Markdown's pain points (significant whitespace,
+noisy links, etc.) And so I slowly let go of the attachment of using
+Org Mode in all the things, and embraced the idea of writing blog
+posts directly in Markdown; this also alleviated the complexity of
+sundry issues arising from exporting from Org to Markdown.
+
+At first, Eleventy looks like a deceptively complex pile of language
+soup: JS, Markdown, templating languages, HTML, and CSS—at times all
+occurring within the same file—all somehow live under one
+roof. However, tweaking the starter project ended up being a
+relatively easy, even pleasant experience.
+
+<a id="painless-deployment"></a>
+# Painless Deployment
+
+Even deployment is simple. This site's content is version-controlled
+locally. I then build the site, then simply `scp` the `_site`
+directory to the appropriate directory in my VPS, where this blog is
+hosted. The previous remote `_site` directory is simply overwritten
+with the new files. I don't need a GitHub workflow, as I did when
+using Hugo with GitHub pages; I don't even need to push to a remote
+repo. Copying the files suffices.
+
+<a id="conclusion"></a>
+# Conclusion
+
+On the one hand, I'm nowhere near able to make something like the
+starter project from scratch. On the other hand, neither am I
+daunted. Eleventy in a sense reminds me of Emacs, in that there's a
+certain joy to be found in its eclectic complexity. I look forward to
+continue using Eleventy as I grow this blog.