Давайте создадим компилятор!

ОглавлениеДобавить в закладки К обложке

{–}

{ Load a Parameter to the Primary Register }

procedure LoadParam(N: integer);

var Offset: integer;

begin

Offset := 8 + 2 * (Base – N);

Emit('MOVE ');

WriteLn(Offset, '(A6),D0');

end;

{–}

{ Store a Parameter from the Primary Register }

procedure StoreParam(N: integer);

var Offset: integer;

begin

Offset := 8 + 2 * (Base – N);

Emit('MOVE D0,');

WriteLn(Offset, '(A6)');

end;

{–}

Идея состоит в том, что значение Base будет заморожено после того, как мы обработаем формальные параметры и не будет увеличиваться дальше когда новые, локальные, переменные будут вставлены в таблицу идентификаторов. Об этом позаботится код в конце FormalList:

{–}

{ Process the Formal Parameter List of a Procedure }

procedure FormalList;

begin

Match('(');

if Look <> ')' then begin

FormalParam;

while Look = ',' do begin

Match(',');

FormalParam;

end;

end;

Match(')');

Fin;

Base := NumParams;

NumParams := NumParams + 4;

end;

{–}

(Мы добавили четыре слова чтобы учесть адрес возврата и старый указатель кадра, который заканчивается между формальными параметрами и локальными переменными.)

Все что мы должны сделать дальше – это установить семантику объявления локальных переменных в синтаксическом анализаторе. Подпрограммы очень похожи на Decl и TopDecls:

{–}

{ Parse and Translate a Local Data Declaration }

procedure LocDecl;

var Name: char;

begin

Match('v');

AddParam(GetName);

Fin;

end;

{–}

{ Parse and Translate Local Declarations }

function LocDecls: integer;

var n: integer;

begin

n := 0;

while Look = 'v' do begin

LocDecl;

inc(n);

end;

LocDecls := n;

end;

{–}

Заметьте, что LocDecls является функцией, возвращающей число локальных переменных в DoProc.

Затем мы изменим DoProc для использования этой информации:

{–}

{ Parse and Translate a Procedure Declaration }

procedure DoProc;

var N: char;

k: integer;

begin

Match('p');

N := GetName;

if InTable(N) then Duplicate(N);

ST[N] := 'p';

FormalList;

k := LocDecls;

ProcProlog(N, k);

BeginBlock;

ProcEpilog;

ClearParams;

end;

{–}

(Я сделал пару изменений, которые не были в действительности необходимы. Кроме небольшой реорганизации я переместил вызов Fin в FormalList а также в LocDecls. Не забудьте поместить его в конец FormalList.)

Обратите внимание на изменения при вызове ProcProlog. Новый параметр – это число слов (не байт) для распределения памяти. Вот новая версия ProcProlog:

{–}

{ Write the Prolog for a Procedure }

procedure ProcProlog(N: char; k: integer);

begin

PostLabel(N);

Emit('LINK A6,#');

WriteLn(-2 * k)

end;

{–}

Сейчас должно работать. Добавьте эти изменения и посмотрите как они работают.


Логин
Пароль
Запомнить меня