{"@attributes":{"version":"2.0"},"channel":{"title":"Multi-Stage Programming on","link":"https:\/\/moleike.github.io\/tags\/multi-stage-programming\/","description":"Recent content in Multi-Stage Programming on","generator":"Hugo","language":"en-US","copyright":"Copyright \u00a9 2025, Alex Moreno.","lastBuildDate":"Mon, 20 Apr 2026 00:00:00 +0000","item":{"title":"Staged Parser Combinators in Scala: Have Your Cake and Eat It (Too)","link":"https:\/\/moleike.github.io\/blog\/staged-parser-combinators\/","pubDate":"Mon, 20 Apr 2026 00:00:00 +0000","guid":"https:\/\/moleike.github.io\/blog\/staged-parser-combinators\/","description":"<p>Parser combinators have a reputation of poor performance&mdash;worst-case\nexponential time&mdash;and deemed good for prototyping but not for production. Or so\nthe story goes. While techniques like Packrat parsing or static analysis offer\nlinear-time guarantees by addressing naive backtracking, they come with their\nown trade-offs.<\/p>\n<p>In this post, I want to explore an optimization route that complements the\nothers: avoiding the performance penalty of abstraction.<\/p>\n<p>By leaning into Scala 3&rsquo;s metaprogramming capabilities, our combinators combine\n<em>code fragments<\/em>. By moving to a <em>staged<\/em> continuation-passing style (CPS)\nencoding, we make the control flow explicit and continuations are fully\nevaluated at compile time. Results show that a staged parser runs ~50% faster\nthan a handwritten recursive descent parser and over 25x faster than a\nnon-staged version. Interestingly, this approach is deeply rooted in partial\nevaluation history, closely mirroring the <a href=\"https:\/\/arxiv.org\/abs\/1611.09906\">First Futamura\nProjection<\/a>.<\/p>"}}}