Storing Identifiers Into Symbol Table
Storing identifiers into symbol table is simple because of the way how Turbo Pascal organizes symbol tables.
StoreCurrentIdentifierToSymbolTable
increases main symbol table, adds the identifier at the end of appropriate list and clears identifier data.
Function StoreCurrentIdentifierToSymbolTable (IdentifierList: PIdentifierList; IdentifierDataSize: Word;
Var NewIdentifier: PIdentifier): Pointer;
Var DataStart: PChar;
LastIdentifier: PIdentifier;
ListEntry: Byte;
begin
NewIdentifier := IncreaseSymbolTable (stMain, 3 + Length (CurrentIdentifier) + 1 + IdentifierDataSize);
ListEntry := (CurrentIdentifierHash and IdentifierList^.Mask) shr 1;
LastIdentifier := Ptr (Seg (IdentifierList^), IdentifierList^.Offset [ListEntry]);
IdentifierList^.Offset [ListEntry] := Ofs (NewIdentifier^);
NewIdentifier^.Next := Ofs (LastIdentifier^);
NewIdentifier^.Token := Token_EndOfLine;
NewIdentifier^.Name.Str := CurrentIdentifier;
DataStart := PChar (NewIdentifier) + 3 + 1 + Length (CurrentIdentifier);
StoreCurrentIdentifierToSymbolTable := DataStart;
FillChar (DataStart^, IdentifierDataSize, 0);
end;
StoreNewIdentifierToSymbolTable
first checks if the identifier is already defined in the current scope. If it is found you get the famous Duplicate Identifier error.
Function StoreNewIdentifierToSymbolTable (NewIdentifierDataSize: Word; Var NewIdentifier: PIdentifier): Pointer;
Var IdentifierDataPtr: Pointer;
IdentifierOffset: Word;
IdToken: TToken;
begin
If CurrentIdentifierDeclaredInCurrentScope (IdentifierOffset, IdentifierDataPtr, IdToken) then
CurrentIdentifierError (DuplicateIdentifier);
StoreNewIdentifierToSymbolTable := StoreCurrentIdentifierToSymbolTable (CurrentScopeIdentifierTableAddress, NewIdentifierDataSize, NewIdentifier);
end;
This function finds the symbol table according to the current scope.
Function CurrentScopeIdentifierTableAddress: PIdentifierList;
Var UnitHeader: PUnitHeader;
ListPtr: PtrRec absolute UnitHeader;
begin
UnitHeader := Ptr (MainSymbolTable.Segment, 0);
If CurrentRecordOrObjectTypeDefinitionOffset <> 0 then
ListPtr.Ofs := PRecordTypeDefinition (Ptr (MainSymbolTable.Segment,
CurrentRecordOrObjectTypeDefinitionOffset))^.FieldsListOffset else
If ProcedureIdentifierDataOffset <> 0 then
ListPtr.Ofs := PProcedureIdentifierData (Ptr (MainSymbolTable.Segment,
ProcedureIdentifierDataOffset))^.LocalIdentifiersList else
ListPtr.Ofs := UnitHeader^.PrivateIdentifiersListOffset;
CurrentScopeIdentifierTableAddress := ListPtr.Ptr;
end;
StoreCommaSeparatedIdentifiers
simply stores one or more identifiers separated with comma. This procedure is used for storing declared variables and fields in records and objects.
Procedure StoreCommaSeparatedIdentifiers;
Var IdData: Pointer;
begin
FirstDeclaredVariableIdentifierOffset := SymbolTable [stMain].UsedSize;
NumberOfDeclaredVariableIdentifiers := 0;
Repeat
ExpectAndStoreIdentifier (SizeOf (TVariableIdentifierData), IdData);
Inc (NumberOfDeclaredVariableIdentifiers);
until not CheckAndGetNextToken (Token_Comma);
end;
Procedure ExpectIdentifier;
begin
If Token <> Token_Identifier then Error (IdentifierExpected);
end;
ExpectAndStoreIdentifier
checks if the current token is identifier and if it is, it is stored in the main symbol table.
Function ExpectAndStoreIdentifier (DataSize: Word; Var IdentifierData: Pointer): PIdentifier;
Var NewIdentifier: PIdentifier;
begin
ExpectIdentifier;
IdentifierData := StoreNewIdentifierToSymbolTable (DataSize, NewIdentifier);
GetNextToken;
ExpectAndStoreIdentifier := NewIdentifier;
end;