Logo for ammarahmed.ca
BackTech
Why and How I Built My Own Programming Language; Qalam cover image
Jan 16, 2025

Why and How I Built My Own Programming Language; Qalam

#Low Level

Programming languages are the backbone of software engineering, the magic wands we wave to make computers do our bidding. But have you ever stopped to wonder how they actually work? What’s under the hood of the syntax you use every day? That’s the question I set out to answer when I decided to create my own programming language: Qalam.

Inspired by Robert Nystrom’s Crafting Interpreters tutorial, I took the scenic route by rewriting the whole thing in Rust instead of Java—because apparently, I enjoy challenging myself. On top of that, I tossed the original syntax out the window and replaced it with something utterly nonsensical yet amusing: Roman-Urdu. Yes, I built a programming language where keywords like agar and warna bring conditional statements to life. Is it useful? Absolutely not. Was it fun to make? You bet.

The point wasn’t to create the next big thing in programming. It was to understand, at a deeper level, how the languages we take for granted actually work. Writing an interpreter from scratch is like building a puzzle where you also have to design the pieces. And by tweaking the tutorial—avoiding copy-paste solutions and adapting it to a new language and syntax—I forced myself to learn, rather than simply follow.

Qalam isn’t here to revolutionize coding. It’s here to remind us that sometimes, the best way to learn is to dive headfirst into something entirely unnecessary, completely impractical, but undeniably interesting.

Before we dive in to how Qalam works, below is a small example of Qalam code to give you a taste of its quirky syntax and features. This example demonstrates a simple function that calculates the factorial of a number using Roman-Urdu keywords:

To learn more about Qalam, check out the GitHub repo. You can also try it out for yourself with the web playground.

1kaam factorial(n) { 2 agar (n == 0) { 3 wapis 1; 4 } 5 wapis n * factorial(n - 1); 6} 7 8bolo(factorial(5)); // outputs: 120

How It Works: A High-level Overview

In the whimsical world of Qalam, three unsung heroes toil behind the scenes to transform your Roman-Urdu-inspired code into executable magic: the Scanner, the Parser, and the Interpreter. Let's take a high-level peek at their roles, without diving too deep into the technical rabbit hole—I'll leave that adventure to you.

Scanner (The Lexical Analyst)

Imagine the Scanner as a meticulous librarian, sifting through the chaotic jumble of characters in your source code. Its mission? To organize this mess into a tidy sequence of tokens—the fundamental building blocks like keywords, identifiers, and symbols. This process, known as scanning or lexing, is akin to turning a stream of consciousness into coherent words.

In essence, it takes the raw text and scans (who would’ve thought) through it looking for strings of characters that match the required syntax. When it finds something, it grabs it and makes it into a token with relevant information like the value and position.

Parser (The Grammar Guru)

Once the Scanner has done its part, the Parser steps in as the grammar guru. It takes the sequence of tokens and assembles them into a structured Abstract Syntax Tree (AST), reflecting the hierarchical nature of the code. Think of the Parser as a linguist diagramming sentences, ensuring that the code's syntax adheres to Qalam's grammatical rules.

The AST is how the code will be executed so it needs to follow the correct logical structure based on the grammatical rules. A very simple case that many will be able to understand is to do with arithmetic. If you are provided with 1 + 1 / 2, BEDMAS (PEMDAS for any Americans) teaches us that it should be evaluated as 1 + 0.5 = 1.5. Therefore, the code needs to reflect things like this and the Parser, parses the tokens in such a manner that these rules are upheld. Similarly, (1 + 1) / 2 would be different than 1 + 1 / 2.

Interpreter (The Executioner)

With the AST in hand, the Interpreter becomes the executioner—though a benevolent one. It traverses the tree, evaluating expressions and executing statements as it goes. In essence, the Interpreter breathes life into the static structure, making the code's behavior manifest. For the initiated, Qalam uses the visitor pattern to traverse the AST and execute statements.

These three components work in harmony to take your Qalam code from mere text to functioning programs. Delving into the nitty-gritty details of their implementation would turn this overview into a novel, so I'll leave that deep dive as an exercise for the intrepid reader.

A Note On Errors

There are essentially three types of errors that can occur; syntax errors (Scanner), grammatical errors (Parser), and runtime errors (Interpreter).

Syntax errors would be if the Scanner sees an unexpected string of characters. These are quite uncommon to be thrown by the Scanner since anything that is “unexpected” will just be treated as an identifier (variable or function name), the unexpectedness is usually handled by the Parser as it will check if an identifier should be in that spot or not.

Grammatical errors occur when it’s not an unexpected string of characters but something is not in the right place or the right order. For example, in Qalam, variables are initialized with rakho a = 1;. If the Parser sees, a rakho = 1; it will throw an error.

Runtime errors are errors that get past everything else and break something will the code is running. A very simple example is a division by zero error.

Takeaway

Creating Qalam wasn’t about building something practical or revolutionizing programming. It was about diving into the deep end, getting my hands dirty, and learning how programming languages work at their core. From scanning tokens to parsing syntax and interpreting code, every step of the process forced me to think critically, solve problems, and appreciate the intricacies of the tools we use every day.

By intentionally stepping away from the comfort zone of pre-made tutorials and adapting the concepts to my own constraints (hello, Rust and Roman-Urdu!), I discovered how much more I could learn by challenging myself. This project reminded me that programming is, at its heart, about curiosity, creativity, and the willingness to explore.

If you’ve ever wondered what goes on behind the scenes of your favorite language—or if you just want a deeper understanding of how code turns into action—I can’t recommend this kind of project enough. It won’t necessarily be easy, but it will absolutely be worth it.

And as for Qalam? It’s not practical or groundbreaking, but it’s mine. And sometimes, that’s all you need to call a project a success.