|
For a class this quarter, I was writing a compiler from scratch in C. For the lexer, we had to have a table mapping current state and current character to next state. Moreover, it was necessary to figure out what states would be needed to produce the desired tokens. Of course, knowing the language beforehand, one could come up with the necessary states and then produce the table by hand, but that is labor-intensive and error-prone, and having the language we were parsing hard-coded into my lexer code did not satisfy me. My first approach was to figure out the states by hand, and then, rather than creating the transition table by hand, I defined a simpler structure near the top of my code which was an array of { current_state, next_state, "characters-resulting-in-this-transition" } arrays. Then, at runtime, I would have to perform initialization to translate this structure into the actual transition table itself. It was at this point that I really wished for the macro power of Lisp, to have the full power of the language at compile time to define structures that would remain static at runtime. As an aside, I ended up writing Python (to figure out both the necessary states and to build the transition table) that generated the C code, and then I added items to my Makefile that would run the Python to create the C and then compile it. If I was using Lisp, I could have done this in a much more straightforward manner. |