10.3. Declarations And Symbols

That looks pretty good, but we're still only generating the null program for output. A real compiler would issue assembler directives to allocate storage for the variables. It's about time we actually produced some code.

With a little extra code, that's an easy thing to do from procedure Decl. Modify it as follows:

{ Parse and Translate a Data Declaration }
procedure Decl;
var Name: char;
begin
   Match('v');
   Alloc(GetName);
end;

The procedure Alloc just issues a command to the assembler to allocate storage:

{ Allocate Storage for a Variable }
procedure Alloc(N: char);
begin
   WriteLn(N, ':', TAB, 'DC 0');
end;

Give this one a whirl. Try an input that declares some variables, such as:

     pvxvyvzbe.

See how the storage is allocated? Simple, huh? Note also that the entry point, “MAIN,” comes out in the right place.

For the record, a “real” compiler would also have a symbol table to record the variables being used. Normally, the symbol table is necessary to record the type of each variable. But since in this case all variables have the same type, we don't need a symbol table for that reason. As it turns out, we're going to find a symbol necessary even without different types, but let's postpone that need until it arises.

Of course, we haven't really parsed the correct syntax for a data declaration, since it involves a variable list. Our version only permits a single variable. That's easy to fix, too.

The BNF for <var-list> is

     <var-list> ::= <ident> (, <ident>)*

Adding this syntax to Decl gives this new version:

{ Parse and Translate a Data Declaration }
procedure Decl;
var Name: char;
begin
   Match('v');
   Alloc(GetName);
   while Look = ',' do begin
      GetChar;
      Alloc(GetName);
   end;
end;

OK, now compile this code and give it a try. Try a number of lines of VAR declarations, try a list of several variables on one line, and try combinations of the two. Does it work?