True, bf is unlike any programming language we’ll ever need or use. But it’s very simple, and thus a great way to try out some of the classic power tools in building languages.
We saw how a grammar is the organizing principle of a language—a tool for explaining its structure. By following the grammar, we can light a path through the implementation. Our time spent writing out the grammar paid off by making the rest of the language easier to think about & snap together.
Every Racket language has a reader; every reader has a read-syntax function; and every read-syntax function will contain some kind of parser. A parser converts a source string into a structured representation called a parse tree.
Rather than build a parser by hand, we used the brag language to convert a grammar into a parse function.
We learned how a tokenizer cooperates with the parser to filter out irrelevant characters from the source string, and categorize others.
In our expander, macros were the glue that let us convert the parse tree produced by our reader into Racket functions that implemented the logic of the bf language.
We learned how to turn a folder of Racket modules into a package, which allowed us to use the neater #lang bf notation at the top of a source file.