Содержание материала

ТАБЛИЦА ИДЕНТИФИКАТОРОВ

Должно быть очевидным, что если мы собираемся работать с переменными различных типов, нам понадобится какое-то место для записи их типов. Очевидным средством для этого является таблица идентификаторов и мы уже использовали ее например для различия между локальными и глобальными переменными и между переменными и процедурами.
    Структура таблицы идентификаторов для одно-символьных токенов особенно проста и мы использовали ее прежде несколько раз. Для работы с ней, мы возьмем некоторые процедуры, которые мы использовали раньше.

Сначала, нам необходимо объявить саму таблицу идентификаторов:

Code:

{ Variable Declarations }

var Look: char;              { Lookahead Character }

    ST: Array['A'..'Z'] of char;   {  *** ДОБАВЬТЕ ЭТУ СТРОКУ ***}

 

    Затем мы должны удостовериться, что она инициализируется в процедуре Init:

Code:

{ Initialize }

procedure Init;

var i: char;

begin

   for i := 'A' to 'Z' do

      ST[i] := '?';

   GetChar;

end;

 
 

 

Следующая процедура в действительности нам не нужна, но она будет полезна для отладки. Все, что она делает, это формирует дамп содержимого таблицы идентификаторов:

Code:

{ Dump the Symbol Table }

procedure DumpTable;

var i: char;

begin

   for i := 'A' to 'Z' do

      WriteLn(i, ' ', ST[i]);

end;

 

 

 

В действительности не имеет значения, где вы поместите эту процедуру... я планирую группировать все подпрограммы таблицы идентификаторов вместе, так что я поместил ее сразу после процедур сообщений об ошибках.

Если вы осторожный тип (как я), вам возможно захотелось бы начать с тестовой программы, которая ничего не делает а просто инициализирует таблицу и затем создает ее дамп. Только для того, чтобы быть уверенным, что все мы находимся на одной волне, ниже я воспроизвожу всю программу, дополненную новыми процедурами. Заметьте, что эта версия включает поддержку пробелов:

Code:

program Types;

 

{ Constant Declarations }

const TAB = ^I;

      CR  = ^M;

      LF  = ^J;

 

{ Variable Declarations }

var Look: char;              { Lookahead Character }

    ST: Array['A'..'Z'] of char;

 

 

{ Read New Character From Input Stream }

procedure GetChar;

begin

   Read(Look);

end;

 

{ Report an Error }

procedure Error(s: string);

begin

   WriteLn;

   WriteLn(^G, 'Error: ', s, '.');

end;

 

{ Report Error and Halt }

procedure Abort(s: string);

begin

   Error(s);

   Halt;

end;

 

{ Report What Was Expected }

procedure Expected(s: string);

begin

   Abort(s + ' Expected');

end;

 

{ Dump the Symbol Table }

procedure DumpTable;

var i: char;

begin

   for i := 'A' to 'Z' do

        WriteLn(i, ' ', ST[i]);

end;

 

{ Recognize an Alpha Character }

function IsAlpha(c: char): boolean;

begin

   IsAlpha := UpCase(c) in ['A'..'Z'];

end;

 

{ Recognize a Decimal Digit }

function IsDigit(c: char): boolean;

begin

   IsDigit := c in ['0'..'9'];

end;

 

{ Recognize an AlphaNumeric Character }

function IsAlNum(c: char): boolean;

begin

   IsAlNum := IsAlpha(c) or IsDigit(c);

end;

 

{ Recognize an Addop }

function IsAddop(c: char): boolean;

begin

   IsAddop := c in ['+', '-'];

end;

 

{ Recognize a Mulop }

function IsMulop(c: char): boolean;

begin

   IsMulop := c in ['*', '/'];

end;

 

{ Recognize a Boolean Orop }

function IsOrop(c: char): boolean;

begin

   IsOrop := c in ['|', '~'];

end;

 

{ Recognize a Relop }

function IsRelop(c: char): boolean;

begin

   IsRelop := c in ['=', '#', '<', '>'];

end;

 

{ Recognize White Space }

function IsWhite(c: char): boolean;

begin

   IsWhite := c in [' ', TAB];

end;

 

{ Skip Over Leading White Space }

procedure SkipWhite;

begin

   while IsWhite(Look) do

      GetChar;

end;

 

{ Skip Over an End-of-Line }

procedure Fin;

begin

   if Look = CR then begin

      GetChar;

      if Look = LF then

         GetChar;

   end;

end;

 

{ Match a Specific Input Character }

procedure Match(x: char);

begin

   if Look = x then GetChar

   else Expected('''' + x + '''');

   SkipWhite;

end;

 

{ Get an Identifier }

function GetName: char;

begin

   if not IsAlpha(Look) then Expected('Name');

   GetName := UpCase(Look);

   GetChar;

   SkipWhite;

end;

 

{ Get a Number }

function GetNum: char;

begin

   if not IsDigit(Look) then Expected('Integer');

   GetNum := Look;

   GetChar;

   SkipWhite;

end;

 

{ Output a String with Tab }

procedure Emit(s: string);

begin

   Write(TAB, s);

end;

 

{ Output a String with Tab and CRLF }

procedure EmitLn(s: string);

begin

   Emit(s);

   WriteLn;

end;

 

{ Initialize }

procedure Init;

var i: char;

begin

   for i := 'A' to 'Z' do

      ST[i] := '?';

   GetChar;

   SkipWhite;

end;

 

{ Main Program }

begin

   Init;

   DumpTable;

end.

 

 

ОК, запустите эту программу. Вы должны получить (очень быстро) распечатку всех букв алфавита (потенциальных идентификаторов) сопровождаемых вопросительным знаком. Не очень захватывающе, но это только начало.

Конечно, вообще-то мы хотим видеть типы только тех переменных, которые были определены. Мы можем устранить другие добавив в DumpTable условие IF. Измените цикл следующим образом:

for i := 'A' to 'Z' do

   if ST[i] <> '?' then

       WriteLn(i, ' ', ST[i]);

Теперь запустите программу снова. Что вы получили?

Хорошо, это даже более скучно чем раньше! Сейчас вообще ничего не выводится, так как в данный момент ни одно из имен не было объявлено. Мы можем немного приправить результат вставив в основную программу несколько операторов, объявляющих несколько записей.  Попробуйте такие:

ST['A'] := 'a';

ST['P'] := 'b';

ST['X'] := 'c';

На этот раз, когда вы запустите программу, вы должны получить распечатку, показывающую, что таблица идентификаторов работает правильно.

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить