10.10. Multi-Character Variable Names

One of those is the restriction that we still have, requiring single-character variable names. Now that we can handle multi-character keywords, this one begins to look very much like an arbitrary and unnecessary limitation. And indeed it is. Basically, its only virtue is that it permits a trivially simple implementation of the symbol table. But that's just a convenience to the compiler writers, and needs to be eliminated.

We've done this step before. This time, as usual, I'm doing it a little differently. I think the approach used here keeps things just about as simple as possible.

The natural way to implement a symbol table in Pascal is by declaring a record type, and making the symbol table an array of such records. Here, though, we don't really need a type field yet (there is only one kind of entry allowed so far), so we only need an array of symbols. This has the advantage that we can use the existing procedure Lookup to search the symbol table as well as the keyword list. As it turns out, even when we need more fields we can still use the same approach, simply by storing the other fields in separate arrays.

OK, here are the changes that need to be made. First, add the new typed constant:

NEntry: integer = 0;

Then change the definition of the symbol table as follows:

const MaxEntry = 100;
var ST   : array[1..MaxEntry] of Symbol;

Note

Note that ST is not declared as a SymTab. That declaration is a phony one to get Lookup to work. A SymTab would take up too much RAM space, and so one is never actually allocated.

Next, we need to replace InTable:

{ Look for Symbol in Table }
function InTable(n: Symbol): Boolean;
begin
   InTable := Lookup(@ST, n, MaxEntry) <> 0;
end;

We also need a new procedure, AddEntry, that adds a new entry to the table:

{ Add a New Entry to Symbol Table }
procedure AddEntry(N: Symbol; T: char);
begin
   if InTable(N) then Abort('Duplicate Identifier ' + N);
   if NEntry = MaxEntry then Abort('Symbol Table Full');
   Inc(NEntry);
   ST[NEntry] := N;
   SType[NEntry] := T;
end;

This procedure is called by Alloc:

{ Allocate Storage for a Variable }
procedure Alloc(N: Symbol);
begin
   if InTable(N) then Abort('Duplicate Variable Name ' + N);
   AddEntry(N, 'v');
.
.
.

Finally, we must change all the routines that currently treat the variable name as a single character. These include LoadVar and Store (just change the type from char to string), and Factor, Assignment, and Decl (just change Value[1] to Value).

One last thing: change procedure Init to clear the array as shown:

{ Initialize }
procedure Init;
var i: integer;
begin
   for i := 1 to MaxEntry do begin
      ST[i] := '';
      SType[i] := ' ';
   end;
   GetChar;
   Scan;
end;

That should do it. Try it out and verify that you can, indeed, use multi-character variable names.