Лекции по построению компилятора на Pascal

ОПЕРАТОР WHILE


Следующий вид оператора должен быть простым, так как мы уже имеем опыт. Синтаксис, который я выбрал для оператора WHILE следующий:

WHILE <condition> <block> ENDWHILE

Знаю, знаю, мы действительно не нуждаемся в отдельных видах ограничителей для каждой конструкции... вы можете видеть, что фактически в нашей одно-символьной версии 'e' используется для всех из них. Но я также помню множество сессий отладки в Паскале, пытаясь отследить своенравный END который по мнению компилятора я хотел поместить где-нибудь еще. По своему опыту знаю, что специфичные и уникальные ключевые слова, хотя они и добавляются к словарю языка, дают небольшую защиту от ошибок, которая стоит дополнительной работы создателей компиляторов.

Теперь рассмотрите, во что должен транслироваться WHILE:

     L1:  <condition>

          BEQ L2

          <block>

          BRA L1

     L2:

Как и прежде, сравнение этих двух представлений дает нам действия, необходимые на каждом этапе:

     WHILE          { L1 = NewLabel;

                      PostLabel(L1) }

     <condition>    { Emit(BEQ L2) }



     <block>

     ENDWHILE       { Emit(BRA L1);

                      PostLabel(L2) }

Код выходит непосредственно из синтаксиса:

{--------------------------------------------------------------}

{ Parse and Translate a WHILE Statement }

procedure DoWhile;

var L1, L2: string;

begin

   Match('w');

   L1 := NewLabel;


   L2 := NewLabel;

   PostLabel(L1);

   Condition;

   EmitLn('BEQ ' + L2);

   Block;

   Match('e');

   EmitLn('BRA ' + L1);

   PostLabel(L2);

end;

{--------------------------------------------------------------}

Так как мы получили новый оператор, мы должны добавить его вызов в процедуру Block:

{--------------------------------------------------------------}

{ Recognize and Translate a Statement Block }

procedure Block;

begin

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

      case Look of

       'i': DoIf;

       'w': DoWhile;

       else Other;

      end;

   end;

end;

{--------------------------------------------------------------}

Никаких других изменений не требуется.

Хорошо, протестируйте новую программу. Заметьте, что на этот раз код <condition> находится внутри верхней метки, как раз там, где нам надо. Попробуйте несколько вложенных циклов. Испробуйте циклы внутри IF и IF внутри циклов. Если вы немного напутаете то, что вы должны набирать, не смущайтесь:  вы пишите ошибки и в других языках, не правда ли?  Код будет выглядеть более осмысленным, когда мы получим полные ключевые слова.

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


Содержание раздела