Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [ 43 ] 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

перенастроить его на другой ЦПУ. Ответ конечно да.

Чтобы сделать это вставьте следующие подпрограммы "генерации кода":

{ Clear the Primary Register }

procedure Clear;

begin

EmitLnCCLR DO); end;

{ Negate the Primary Register }

procedure Negate;

begin

EmitLnCNEG DO); end;

{ Load a Constant Value to Primary Register }

procedure LoadConst(n: integer);

begin

EmitCMOVE #);

WriteLn(n, ,D0); end;

{ Load a Variable to Primary Register }

procedure LoadVar(Name: char);

begin

if not InTable(Name) then Undefined(Name); EmitLnCMOVE + Name + (PC),D0); end;

{ Push Primary onto Stack }

procedure Push;

begin

EmitLnCMOVE D0,-(SP)); end;

{ Add Top of Stack to Primary }

procedure PopAdd;

begin

EmitLnCADD (SP)+,D0); end;

{ Subtract Primary from Top of Stack }

procedure PopSub;

begin

EmitLnCSUB (SP)+,D0); EmitLnCNEG D0); end;

{ Multiply Top of Stack by Primary }

procedure PopMul;

begin



EmitLnCMULS (SP) + ,D0); end;

{ Divide Top of Stack by Primary }

procedure PopDiv;

begin

EmitLnCMOVE (SP) + ,D7); EmitLnCEXT.L D7); EmitLnCDIVS D0,D7); EmitLnCMOVE D7,D0); end;

{ Store Primary to Variable } procedure Store(Name: char); begin

if not InTable(Name) then Undefined(Name); EmitLnCLEA + Name + (PC),A0); EmitLnCMOVE D0,(A0)) end;

Приятная особенность такого подхода, конечно, в том что мы можем перенастроить компилятор на новый ЦПУ просто переписав эти процедуры "генератора кода". Кроме того, позднее мы обнаружим что можем улучшить качество кода немного подправляя эти процедуры без необходимости изменения компилятора.

Обратите внимание, что и LoadVar и Store проверяют таблицу идентификаторов чтобы удостовериться, что переменная определена. Обработчик ошибки Undefined просто вызывает Abort:

{ Report an Undefined Identifier } procedure Undefined(n: string); begin

Abort(Undefined Identifier + n); end;

Итак, теперь мы наконец готовы начать обработку выполнимого кода. Мы сделаем это заменив пустую версию процедуры Assignment.

Мы проходили этот путь много раз прежде, так что все это должно быть вам знакомо. Фактически, если бы не изменения, связанные с генерацией кода, мы могли бы просто скопировать процедуры из седьмой части. Так как мы сделали некоторые изменения я не буду их просто копировать, но мы пройдем немного быстрее, чем обычно. БНФ для операций присваивания:

<assignment> ::= <ident> = <expression> <expression> ::= <first term> ( <addop> <term> )* <first term> ::= <first factor> <rest> <term> ::= <factor> <rest> <rest> ::= ( <mulop> <factor> )* <first factor> ::= [ <addop> ] <factor> <factor> ::= <var> <number> ( <expression> ) Эта БНФ также немного отличается от той, что мы использовали раньше... еще одна "вариация на тему выражений". Эта специфичная версия имеет то, что я считаю лучшей



обработкой унарного минуса. Как вы увидите позднее, это позволит нам очень эффективно обрабатывать отрицательные константы. Здесь стоит упомянуть, что мы часто видели преимущества "подстраивания" БНФ по ходу дела, с цель сделать язык легким для анализа. То, что вы видете здесь, немного другое: мы подстраиваем БНФ для того, чтобы сделать генерацию кода более эффективной! Это происходит впервые в этой серии.

Во всяком случае, следующий код реализует эту БНФ:

{ Parse and Translate a Math Factor } procedure Expression; Forward; procedure Factor; begin

if Look = ( then begin MatchCC); Expression; MatchC)); end

else if IsAlpha(Look) then

LoadVar(GetName) else

LoadConst(GetNum);

end;

{ Parse and Translate a Negative Factor }

procedure NegFactor;

begin

Match(-); if IsDigit(Look) then LoadConst(-GetNum) else begin Factor; Negate; end; end;

{ Parse and Translate a Leading Factor }

procedure FirstFactor;

begin

case Look of +: begin

Match(+); Factor; end;

-: NegFactor; else Factor; end; end;



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [ 43 ] 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97