Анимация
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

L2 := L1;

EmitLnCBEQ + L1);

Block;

if Look = l then begin Match(4);

L2 := NewLabel;

EmitLnCBRA + L2);

PostLabel(L1); Block;

end;

PostLabel(L2);

MatchCe);

end;

{ Parse and Translate an Assignment Statement } procedure Assignment; var Name: char; begin

Name := GetName;

Match(=);

Expression;

EmitLn(LEA + Name + (PC),A0); EmitLn(MOVE D0,(A0));

end;

{ Recognize and Translate a Statement Block }

procedure Block;

begin

while not(Look in [e, l]) do begin case Look of

i: DoIf;

CR: while Look = CR do Fin;

else Assignment; end; end;

end;

{ Parse and Translate a Program }

procedure DoProgram;

begin

Block;

if Look <> e then Expected(END); EmitLn(END)

end;

{ Initialize } procedure Init; begin

LCount := 0;

GetChar;



{ Main Program } begin Init;

DoProgram;

end.

Пара комментариев:

• Форма синтаксического анализатора выражений, использующего FirstTerm и т.п., немного отличается от того, что вы видели ранее. Это еще одна вариация на ту же самую тему. Не позволяйте им вертеть вами... изменения необязательны для того, что будет дальше.

• Заметьте, что как обычно я добавил вызовы Fin в стратегических местах для поддержки множественных строк.

Прежде чем приступить к добавлению сканера, сначала скопируйте этот файл и проверьте, что он действительно корректно выполняет анализ. Не забудьте "кода": "i" для IF, "l" для ELSE и "e" для ELSE или ENDIF.

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

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

Многосимвольная версия показана ниже. Чтобы получить ее я сделал следующие изменения:

• Добавлены переменные Token и Value и определения типов, необходимые для Lookup.

• Добавлено определение KWList и KWcode.

• Добавлен Lookup.

• GetName и GetNum заменены их многосимвольными версиями. (Обратите внимание, что вызов Lookup был перемещен из GetName, так что он не будет выполняться внутри выражений).

• Создана новая, рудиментарная Scan, которая вызывает GetName затем сканирует ключевые слова.

• Создана новая процедура MatchString, которая ищет конкретное ключевое слово. Заметьте, что в отличие от Match, MatchString не считывает следующее ключевое слово.

• Изменен Block для вызова Scan.

• Немного изменены вызовы Fin. Fin теперь вызывается из GetName.



Программа полностью:

program KISS;

{ Constant Declarations }

const TAB = CR = LF =

{ Type Declarations } type Symbol = string[8];

SymTab = array[1..1000] of Symbol;

TabPtr = SymTab;

{ Variable Declarations }

var Look : char; { Lookahead Character }

Token : char; { Encoded Token }

Value : string[16]; { Unencoded Token

Lcount: integer; { Label Counter }

{ Definition of Keywords and Token Types } const KWlist: array [1..4] of Symbol =

(IF, ELSE, ENDIF, END); const KWcode: string[5] = xilee;

{ 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;

{ Recognize an Alpha Character } function IsAlpha(c: char): boolean; begin

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

{ Recognize a Decimal Digit }



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