/util/symtable.pas
unit SymTable;

interface

type
    PSymbolEntry = ^SymbolEntry;
    SymbolEntry = record
        name: string[32];
        value: Word;
        next: PSymbolEntry;
    end;
    SymbolTable = record
        head: PSymbolEntry;
        entries: Word;
    end;

procedure DefineSymbol(var table: SymbolTable; const n: String; const value: Word);
function FindSymbolTableEntry(const table: SymbolTable; const n: string): PSymbolEntry;
function FindSymbol(const table: SymbolTable; const n: String; var value: Word): Boolean;
procedure DumpSymbols(const table: SymbolTable);

implementation

uses Parse, Util;

function GetTableEnd(const table: SymbolTable): PSymbolEntry;
var p: PSymbolEntry;
begin
    p := table.head;
    while p <> nil do begin
        if p^.next = nil then begin
            GetTableEnd := p;
            Exit;
        end;
        p := p^.next;
    end;
end;

procedure DefineSymbol(var table: SymbolTable; const n: String; const value: Word);
var p: PSymbolEntry;
    new_entry: PSymbolEntry;
begin
    if FindSymbolTableEntry(table, n) <> nil then begin
        ErrorAtLine('Symbol ''' + n + ''' already defined');
        Halt(1);
    end;
    if table.head = nil then begin
        New(table.head);
        new_entry := table.head;
    end
    else begin
        p := GetTableEnd(table);
        New(new_entry);
        p^.next := new_entry;
    end;
    new_entry^.name := ToUpCase(n);
    new_entry^.value := value;
    new_entry^.next := nil;
    Inc(table.entries);
end;

function FindSymbolTableEntry(const table: SymbolTable; const n: string): PSymbolEntry;
var p: PSymbolEntry;
begin
    p := table.head;
    while p <> nil do begin
        if p^.name = n then begin
            FindSymbolTableEntry := p;
            Exit;
        end;
        p := p^.next;
    end;
    FindSymbolTableEntry := nil;
end;

function FindSymbol(const table: SymbolTable; const n: String; var value: Word): Boolean;
var p: PSymbolEntry;
begin
    p := FindSymbolTableEntry(table, n);
    if p <> nil then begin
        FindSymbol := true;
        value := p^.value;
    end
    else
        FindSymbol := false;
end;

procedure DumpSymbols(const table: SymbolTable);
var p: PSymbolEntry;
begin
    p := table.head;
    while p <> nil do begin
        Writeln(p^.name, ': ', p^.value);
        p := p^.next;
    end;
end;

end.