2.2. Single Digits

In keeping with the whole theme of this series (KISS, remember?), let's start with the absolutely most simple case we can think of. That, to me, is an expression consisting of a single digit.

Before starting to code, make sure you have a baseline copy of the cradle that I gave last time. We'll be using it again for other experiments. Then add this code:

{ Parse and Translate a Math Expression }
procedure Expression;
begin
   EmitLn('MOVE #' + GetNum + ',D0')
end;

And add the line “Expression;” to the main program so that it reads:

begin
   Init;
   Expression;
end.

Now run the program. Try any single-digit number as input. You should get a single line of assembler-language output. Now try any other character as input, and you'll see that the parser properly reports an error.

Congratulations! You have just written a working translator!

OK, I grant you that it's pretty limited. But don't brush it off too lightly. This little “compiler” does, on a very limited scale, exactly what any larger compiler does: it correctly recognizes legal statements in the input “language” that we have defined for it, and it produces correct, executable assembler code, suitable for assembling into object format. Just as importantly, it correctly recognizes statements that are not legal, and gives a meaningful error message. Who could ask for more? As we expand our parser, we'd better make sure those two characteristics always hold true.

There are some other features of this tiny program worth mentioning. First, you can see that we don't separate code generation from parsing … as soon as the parser knows what we want done, it generates the object code directly. In a real compiler, of course, the reads in GetChar would be from a disk file, and the writes to another disk file, but this way is much easier to deal with while we're experimenting.

Also note that an expression must leave a result somewhere. I've chosen the 68000 register D0. I could have made some other choices, but this one makes sense.