Рисунок 27.1. Определение на метаМини, позволяющее понять действие <инструкции цикла>. Это «определение» влечет за собой обязательное перевычисление <цели цикла>.
<инструкция цикла>::= <простая инструкция цикла>
|<метка> <простая инструкция цикла>
<простая инструкция цикла>::= <заголовок цикла> <тело цикла> <конец цикла>
<заголовок цикла>::= <для> <цель цикла> <управление> DO
<тело цикла> ::= <тело сегмента>
<конец цикла>::= END FOR;
|END FOR <идентификатор>;
<для>::= FOR
<цель цикла>::= <переменная> <заменить на>
<управление>::= <шаговое управление>
|<шаговое управление> <условное управление>
<шаговое управление> ::= <начальное значение> <шаг>
|<начальное значение> <предел>
|<начальное значение> <шаг> <предел>
<начальное значение>::= <выражение>
<шаг>::= BY <выражение>
<предел>::= ТО <выражение>
<условное управление>::= WHILE <выражение>
Проще всего объяснить поведение <инструкции цикла>, написав на «метаМини» небольшой фрагмент, заменяющий эту инструкцию. Чтобы найти результат работы <инструкции цикла>, нужно применить к ней «определение», данное на рис. 27.1. Подчеркнем, что, согласно этому определению, <цель цикла>, <предел> и <шаг> перевычисляются при каждом повторении. Предикат «существует» позволяет метаМини узнать, присутствуют ли соответствующие необязательные части в конкретной <инструкции цикла>. Если употреблен закрывающий <идентификатор>, он должен совпадать с <обязательно присутствующей> <меткой>.
В данном определении <инструкции цикла> педагог вновь победил практика. Динамическое переопределение управляющих значений унаследовано из Алгола; большинство других языков отказалось от этого по соображениям эффективности. Однако, если вы сможете реализовать динамическое определение, полученных знаний с избытком хватит на построение более простых статических циклов. Шаговый и условный циклы соединены в одной инструкции, чтобы сделать Мини поменьше; в реальном языке их можно разделить. Соблюдайте осторожность при повторной обработке <цели цикла>; если цель — это формальный параметр или элемент массива, при каждом повторении за целью могут скрываться различные переменные.
<инструкция выбора>::=<простая инструкция выбора>
|<метка> <простая инструкция выбора>
<простая инструкция выбора> ::= <заголовок инструкции выбора> <тело инструкции выбора> <конец инструкции выбора>
<заголовок инструкции выбора> ::= SELECT <выражение> OF
<тело инструкции выбора>::=<список случаев>
|<список случаев> <прочие случаи>
<конец инструкции выбора> ::= END SELECT;
|END SELECT <идентификатор>;
<список случаев> ::= <случай>
|<список случаев> <случай>
<случай> ::= <заголовок случая> <тело случая>
<заголовок случая> ::= CASE <селектор>:
<селектор>::= <заголовок селектора>)
<заголовок селектора>::= <<выражение>
|<заголовок селектора>, <выражение>
<прочие случаи>::=<заголовок прочих случаев> <тело случая>
<заголовок прочих случаев> ::= OTHERWISE:
<тело случая> ::= <тело сегмента>
<Инструкция выбора> работает следующим образом.
Вычисляется <выражение> в <заголовке инструкции выбора>. Обрабатываются все <случаи>, от первого до последнего, в <списке случаев>. Для каждого <случая>, слева направо, одно за другим вычисляются <выражения> в <селекторе>. Как только <выражение> вычислено, его значение сравнивается со значением первоначального <выражения> из <заголовка инструкции выбора>. Если они равны, выполняется соответствующее <тело случая>; на этом <инструкция выбора> завершает свою работу, и управление передается на следующую < инструкцию>.
Если ни один из случаев не выбран и если имеются <прочие случаи>, выполняется <тело случая> и <инструкция выбора> завершает работу. Иначе <инструкция выбора> ни на что не влияет, если не считать побочных эффектов от вычисления выражений.
Типы всех выражений, используемых для выбора <случая>, должны быть одинаковы. Если в конце <инструкции выбора> употреблен <идентификатор>, он должен совпадать с <обязательно присутствующей> <меткой> <инструкции выбора>.