Reklama

Присваивание

Итак, к этому моменту мы имеем синтаксический анализатор, работающий очень хорошо. Я хотел бы подчеркнуть, что мы получили это, используя всего 88 строк выполнимого кода, не считая того, что было в Cradle. Откомпилированный объектный файл занял 4752 байта. Неплохо, учитывая то, что мы не слишком старались сохранять размеры как исходного так и объектного кода. Мы просто придерживались принципа KISS.
Конечно, анализ выражений не настолько хорош без возможности что-либо делать с его результатами. Выражения обычно (но не всегда) используются в операциях присваивания в форме:
<Ident> = <Expression>
Мы находимся на расстоянии вздоха от возможности анализировать операции присваивания, так что давайте сделаем этот последний шаг. Сразу после процедуры Expression добавьте следующую новую процедуру:

Parse and Translate an Assignment Statement
procedure Assignment;
var Name: char;
begin
Name := GetName;
Match(‘=’);
Expression;
EmitLn(‘LEA ‘ + Name + ‘(PC),A0′);

Теперь нам необходимо изменить функцию GetName так, чтобы она возвращала строку вместо символа:

Get an Identifier
function GetName: string;
var Token: string;
begin
Token := ”;
if not IsAlpha(Look) then Expected(‘Name’);
while IsAlNum(Look) do begin
Token := Token + UpCase(Look);
GetChar;
end;
GetName := Token;
end;

Аналогично измените GetNum следующим образом:

Get a Number
function GetNum: string;
var Value: string;
begin
Value := ”;
if not IsDigit(Look) then Expected(‘Integer’);
while IsDigit(Look) do begin
Value := Value + Look;
GetChar;
end;
GetNum := Value;
end;

Достаточно удивительно, что это фактически все необходимые изменения! Локальная переменная Name в процедурах Ident и Assignment были первоначально объявлены как «char» и теперь должны быть объявлены как string[8]. (Ясно, что мы могли бы сделать длину строки больше, если бы захотели, но большинство ассемблеров в любом случае ограничивают длину.) Внесите эти изменения и затем откомпилируйте и протестируйте. Сейчас вы верите, что это просто?

Reklama