// HACKER NEWS — CYBERSECURITY
Parsing Expression Grammar vs. Regexes: Building Org Parser in Lisp, Export HTML
Hi everyone. In this blog post I want to take you in an adventure of parsing Org mode with Parsing Expression Grammars (PEG) in Guile Scheme (ice-9 peg) and converting to HTML (via SXML): OrgWebAlchemy.
I wanted to share something with you all that I’ve been working on for a while. It all started with some naive regular expressions to parse Org mode content, but I pretty quickly realized I needed something smarter than that to get to where I want to. It’s taken a while but I am finally more knowledgeable of what Parsing Expression Grammars can do, thanks to GNU’s great (ice-9 peg) module and tutorials.
I thought it might be interesting to people here who enjoy Lisp, Scheme, parsing, Org mode, or the general idea of meta-meta-meta-programming as I like to call it. Disclosure, AI has helped me get a grip of PEG and debug some things, but development of OrgWebAlchemy is “my own spaghetti” and the unit tests and manual verification (and lots of pretty printing the AST) has guided me towards quite a nice implementation (if I may say so myself).
Project’s source code @ Codeberg: https://codeberg.org/jjba23/orgwebalchemy
OrgWebAlchemy is a Guile Scheme library for parsing Org-mode documents into an AST and rendering them to HTML. My main use-case is to export Org to HTML without needing Emacs, and to integrate this feature into some projects of mine, allowing me to write Org mode and have it pretty rendered.
But the interesting part is what happens in between.
See here an example showing how OrgWebAlchemy enables the LucidPlan project to render pretty Org mode to HTML
Org-mode looks simple until you actually try to parse it. Headings are easy. A paragraph is easy. A list is easy (wait actually no, this has made me sweat).
At this point, the usual approach of adding another regular expression starts to become somewhat… adventurous. :-)
match this,
unless that follows it,
except inside this block,
unless it is a description,
but don’t consume the newline,
unless the previous line was a list item…