ПАСКАЛЬ
ОПИСАНИЕ ЯЗЫКА

1. ОБЩИЕ СВЕДЕНИЯ

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

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

За основу для Паскаля был взят Алгол-60, откуда в первую очередь заимствованы принципы структурирования и форма выражения.

Главные дополнения по сравнению с Алголом-60 относятся к способам структурирования данных, поскольку недостаточность последних в Алголе-60 была признана главной причиной относительной узости области его применения. Введение записей и файлов сделало возможным решать с помощью Паскаля коммерческие задачи или по крайней мере позволило успешно демонстрировать подобные задачи в курсах программирования.

Алгоритмы и программы вычислительной машины состоят из двух частей: описания действий, которые должны быть осуществлены, и описания обрабатываемых этими действиями данных. Действия задаются так называемыми операторами, а данные - описаниями и определениями.

Данные представлены значениями переменных. Каждая переменная, входящая в некоторый оператор, должна быть введена некоторым описанием переменной, которое приписывает этой переменной идентификатор и тип данных. Именно тип данных определяет множество значений, которое может принимать данная переменная. В Паскале тип может быть задан либо прямо в описании переменной, либо указан идентификатором типа, в последнем случае этот идентификатор должен быть введён явным определением типа.

Базисными являются скалярные типы данных. Их определение задаёт упорядоченное множество значений, т.е. вводит идентификаторы, обозначающие каждое значение этого множества. Помимо скалярных типов, вводимых определениями, в Паскале имеется четыре стандартных скалярных типа: логический "BOOLEAN", целый "INTEGER", литерный "CHAR" и вещественный "REAL". Значения этих типов, кроме логического, обозначаются не идентификаторами, а числами и заключёнными в кавычки литералами, которые синтаксически отличны от идентификаторов. Множество значений литерного типа - это множество литер, имеющихся на печатном устройстве данной установки (КОИ-7).

Тип можно определить как отрезок некоторого скалярного типа - указанием наименьшего и наибольшего значений отрезка.

Структурные типы данных определяются заданием типа их компонент и указанием способа организации. Способы организации отличаются механизмом извлечения компонент из переменной сложного типа. В Паскале имеется четыре способа организации данных: массив, запись, множестве и файл.

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

При организации данных в запись компоненты (называемые полями) могут быть разного типа. Чтобы тип выбираемой компоненты можно было установить прямо по тексту программы (без её исполнения), селекторы записей не содержат вычисляемых значений, а являются идентификаторами, однозначно определяющими извлекаемую компоненту. Эти идентификаторы описываются в определении типа записи, поэтому время доступа к выбираемой компоненте не зависит от селектора и, следовательно, записи также являются структурами с произвольным доступом.

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

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

Файл - это последовательность однотипных компонент. Она определяет естественное упорядочение компонент. В каждый момент непосредственно доступна только одна компонента. Доступ к другим компонентам можно получить в результате последовательного продвижения по файлу. Файл заполняется последовательным присоединением новых компонент к концу файла. Определение типа файла не задаёт числа его компонент.

Переменные, заданные явными описаниями, называются статическими. Описание связывает с переменной некоторый идентификатор, используемый для указания этой переменной. С другой стороны, переменные могут создаваться некоторым оператором. При таком динамическом создании переменной выдаётся так называемый указатель (заменяющий явный идентификатор). Он используется впоследствии для указания на такую переменную. Этот указатель может быть присвоен переменным типа указатель. Каждая переменная - указатель может принимать только значения, являющиеся указателями на значения одного и того же типа "T"; говорят, что она закреплена за этим типом "T". Она может, впрочем, получить также значение "NIL", которое не указывает ни на какую переменную. Поскольку переменные - указатели могут быть компонентами создаваемых динамических переменных структурных типов, то с помощью этих указателей можно представлять любые конечные графы.

Основным оператором является оператор присваивания, который приписывает присвоить только что вычисленное значение некоторой переменной (или компоненте переменной). Значение может быть получено в результате вычисления выражения. Выражения состоят из переменных, констант, множеств, операций и функций, которые выполняют действия над изображёнными величинами и выдают новые значения. Переменные, константы и функции либо описываются в программе, либо являются стандартными объектами. Паскаль содержит фиксированный набор операций, каждая из которых может рассматриваться как отображение из типов операндов в тип результата. Все операции делятся на четыре группы:

  1. арифметические операции - сложение, вычитание, изменение знака, умножение, деление и нахождение остатка;
  2. логические операции - отрицание, дизъюнкция, конъюнкция;
  3. операции над множествами - объединение, пересечение, разность;
  4. операции-отношения - равенство, неравенство, порядок, принадлежность и включение (для множеств).

Результаты операций отношений принадлежат логическому типу. Отношения порядка применимы только к скалярным типам.

Оператор процедуры вызывает исполнение соответствующей процедуры (см. ниже). Операторы присваивания и процедуры являются "кирпичиками" или компонентами, из которых строятся структурные операторы, предписывающие последовательное, выборочное или повторное исполнение своих компонент. Последовательное исполнение операторов задаётся составным оператором, условное или выборочное исполнение - оператором "Если" и оператором "Выбор", а повторное исполнение - циклами. Оператор "Если" служит для подчинения исполнения оператора значению выражения логического типа, а оператор "Выбор" делает возможным выбор между несколькими операторами в соответствии со значением некоторого селектора. Цикл с параметрами (оператор "Для") употребляется, когда число итераций известно заранее, а в остальных случаях используются циклы с условием продолжения (оператор "Пока") или циклы с условием окончания (оператор "Повтор").

Оператору может быть дано имя (идентификатор), с помощью которого можно обращаться к этому оператору. Такой оператор называется процедурой, а его описание - описанием процедуры. Описание может содержать множество описаний переменных, определение типов и дальнейшее описание процедур. Так описанные переменные, типы и процедуры могут упоминаться только в пределах самой процедуры и поэтому называются локальными для данной процедуры. Их идентификаторы имеют смысл только в пределах программного текста, составляющего описание процедуры и называемого областью определения этих идентификаторов. Поскольку одна процедура может быть описана как локальная по отношению к другой, области определения могут быть вложены одна в другую. Объекты, описанные в главной программе, т.е. не локальные ни для какой процедуры, называются глобальными.

Процедура имеет фиксированное число параметров, каждый из которых изображается в пределах процедуры некоторым идентификатором, называемым формальным параметром. При обращении к процедуре каждому формальному параметру должна быть сопоставлена некоторая фактическая величина. Эта величина называется фактическим параметром. Существует три рода параметров: значения, переменные, процедуры (функций). В первом случае фактический параметр является выражением, значение которого вычисляется один раз. Соответствующий формальный параметр является локальной переменной, которой присваивается результат этого вычисления перед выполнением процедуры (функции). В случае параметра-переменной фактический параметр является переменной и формальный параметр служит обозначением этой переменной. Значения индексов, если они есть, вычисляются перед выполнением процедуры (функции). В случае параметра-процедуры или параметра-функции фактическим параметром является идентификатор процедуры или функции.

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

2. СПОСОБ ОПИСАНИЯ ЯЗЫКА

В соответствии с традиционными формами Бэкуса-Наура синтаксические конструкции обозначаются словами, заключёнными в угловые скобки "<" и ">". Эти слова описывают также природу или смысл данных конструкций и используются в последующем описании семантики. Возможное повторение некоторой конструкции указывается звёздочкой (* - ноль или более повторений), а также знаком логическое "И" (& - одно или несколько повторений). Если повторяемая конструкция состоит более чем из одного элемента, она заключается в метаскобки "(*" и "*)", что означает повторение ноль или несколько раз.

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

  <БУКВА>::=А!B!C!D!E!F!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Z!
            А!Б!В!Г!Д!Е!Ж!З!И!Й!К!Л!М!Н!О!П!Р!С!Т!У!Ф!Х!Ц!Ы!Ь!Я
  <ВОСЬМЕР.ЦИФРА>::=0!1!2!3!4!5!6!7
  <ЦИФРА>::=<ВОСЬМЕР.ЦИФРА>!8!9
  <СПЕЦИАЛЬНЫЙ СИМВОЛ>::=+!-!*!/!NOT!AND!OR!=!<>!>!<!<=!>=!
            (!)![!]!:=!.!,!;!:!'!^!DIV!MOD!NIL!IN!IF!THEN!
            ELSE!CASE!OF!REPEAT!UNTIL!WHILE!DO!FOR!TO!
            DOWNTO!BEGIN!END!WITH!GOTO!CONST!VAR!TYPE!
            ARRAY!RECORD!SET!FILE!FUNCTION!PROCEDURE!
            LABEL!PACKED

Конструкция:

<СКОБКА><ЛЮБАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ СИМВОЛОВ, НЕ ВКЛЮЧАЮЩАЯ <СКОБКУ> И "Ш,Щ",><СКОБКА> называется комментарием и может быть вставлена между любыми двумя идентификаторами, числами или специальными символами. Комментарий может быть удалён из текста программы без изменения его значения.

В Паскале допускается три типа <скобок> для выделения комментариев:

<СКОБКА>::={...} ! (*...*) ! /*...*/

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

3. ЭЛЕМЕНТЫ И ОСНОВНЫЕ КОНСТРУКЦИИ ЯЗЫКА

Идентификаторы служат для обозначения констант, типов, переменных, процедур и функций. В пределах области определённости идентификатора, т.е. в процедуре или в функции, в которой он описан, смысл идентификатора должен быть однозначным.

<ИДЕНТИФИКАТОР>::=<БУКВА><БУКВА ИЛИ ЦИФРА>*
<БУКВА ИЛИ ЦИФРА>::=<БУКВА> ! <ЦИФРА>

Паскаль допускает любую длину идентификаторов, причём все знаки являются значимыми. Знаки кириллицы (за исключением ч,ш,щ,э,ю) могут также использоваться, но будут интерпретироваться как и соответствующие латинские. Следует заметить, что в стандарте Паскаля рекомендуется, чтобы первые 8 знаков идентификаторов были уникальными.

В связи с ограничениями на формат объектного модуля идентификаторы внешних фортрановских процедур должны быть уникальными по первым 6-ти знакам.

Для чисел, являющихся константами целого или вещественного типа, используется обычная десятичная система записи буква "Е", предшествующая порядку, читается как "Умножить на 10 в степени".

  <ЦЕЛОЕ БЕЗ ЗНАКА>::= <ЦИФРА>& ! <ВОСЬМЕР.ЦИФРА>&В
  <ВЕЩЕСТВЕННОЕ БЕЗ ЗНАКА>::= <ЦИФРА>&.<ЦИФРА>& ! 
                              <ЦИФРА>&.<ЦИФРА>&Е<ПОРЯДОК> ! 
                                       <ЦИФРА>&Е<ПОРЯДОК>
  <ЧИСЛО БЕЗ ЗНАКА>::= <ЦЕЛОЕ БЕЗ ЗНАКА> ! <ВЕЩЕСТВЕННОЕ БЕЗ ЗНАКА>
  <ПОРЯДОК>::= <ЦИФРА>& ! <ЗНАК><ЦИФРА>&
  <ЗНАК>::= + ! -

Примеры:

  1    100    0.1    5Е-3    87.35Е+8    12В

Последовательности литер, заключённые в кавычки, называются текстами. Тексты, состоящие из единственной литеры, являются константами литерного типа. Тексты, состоящие из N (N>1) литер, заключённых в кавычки, являются константами типа:

ARRAY[1..N] OF CHAR

ПРИМЕЧАНИЕ. Если текст должен содержать кавычку, то она повторяется дважды:

  <ТЕКСТ>::= '<ЛИТЕРА>&'

Примеры:

  'A'     ';'      ''''     'PASCAL'

4. ЭЛЕМЕНТЫ И ВВОД ВЫВОД ДАННЫХ

4.1. Определения констант

Определение константы вводит идентификатор как синоним некоторой константы:

  <ИДЕНТИФИКАТОР КОНСТАНТЫ>::= <ИДЕНТИФИКАТОР>
  <КОНСТАНТА БЕЗ ЗНАКА>::= <ЧИСЛО БЕЗ ЗНАКА> !
                           <ТЕКСТ> ! <ИДЕНТИФИКАТОР КОНСТАНТЫ> ! NIL
  <КОНСТАНТА>::= <ЧИСЛО БЕЗ ЗНАКА> ! <ЗНАК><ЧИСЛО БЕЗ ЗНАКА> !
                 <ИДЕНТИФИКАТОР КОНСТАНТЫ> !
                 <ЗНАК><ИДЕНТИФИКАТОР КОНСТАНТЫ> !
                 <ТЕКСТ>
  <ОПРЕДЕЛЕНИЕ КОНСТАНТЫ>::= <ИДЕНТИФИКАТОР> = <КОНСТАНТА> 

В каждой реализации определены следующие стандартные идентификаторы:

EOL - равен управляющему символу, обозначающему конец строки;

ALFALENG - равен 10.

4.2. Определения типов данных

Тип данных задаёт множество значений, которые могут принимать переменные этого типа, и связывает с этим типом идентификатор.

  <ТИП>::= <ПРОСТОЙ ТИП> ! <СТРУКТУРНЫЙ ТИП> ! <ТИП УКАЗАТЕЛЯ>
  <ОПРЕДЕЛЕНИЕ ТИПА>::= <ИДЕНТИФИКАТОР> = <ТИП>

4.2.1. Простые типы

  <ПРОСТОЙ ТИП>::= <СКАЛЯРНЫЙ ТИП> ! <ОТРЕЗОК ТИПА> ! <ИДЕНТИФИКАТОР ТИПА>
  <ИДЕНТИФИКАТОР ТИПА>::= <ИДЕНТИФИКАТОР>
4.2.1.1. Скалярные типы

Скалярный тип определяет упорядоченное множество значений посредством перечисления идентификаторов, обозначающих эти значения:

  <СКАЛЯРНЫЙ ТИП>::=(<ИДЕНТИФИКАТОР>(*,<ИДЕНТИФИКАТОР>*))

Примеры:

(КРАСН, ОРАНЖ, ЖЁЛТ, ЗЕЛ, ГОЛУБОЙ)
(ЯНВАРЬ, ФЕВРАЛЬ, МАРТ)
(ЗИМА, ВЕСНА, ЛЕТО, ОСЕНЬ)

Ко всем скалярным типам (исключая REAL) применимы следующие функции:

SUCC - следующее значение (в порядке перечисления);

PRED - предшествующее значение (в порядке перечисления).

4.2.1.2. Стандартные скалярные типы

Следующие типы являются стандартными в Паскале:

Целый тип (INTEGER) - значения образуют подмножество целых чисел в границах (-32768..32767). Беззнаковые целые могут быть объявлены с помощью диапазона (0..65535). Следует помнить, что арифметические переполнения определяются только при умножении и делении знаковых целых.

  TYPE UNSIGNEDIGIT=0..65535

Для целых чисел определён идентификатор MAXINT=32767.

Вещественный тип (REAL) - значения являются подмножеством множества вещественных чисел вещественные числа (REAL) имеют диапазон 1Е-38..1Е+38 и точность порядка 7-ми десятичных знаков. Арифметические переполнения определяются для всех операций, а потеря значимости не диагностируется и приводит к нулевому результату. Стандартные трансцендентные функции имеют точность до 6 десятичных цифр.

Логический тип (BOOLEAN) - значения представляют собой истинные значения, обозначаемые идентификаторами TRUE и FALSE;

Литерный тип (CHAR) - значения суть множество литер, зависящее от конкретной реализации, и изображаются самими литерами, заключёнными в кавычки. В данной реализации использует полный набор знаков КОИ-7. Каждый знак хранится в одном байте (8 разрядов).

4.2.1.3. Отрезки типов

Тип может быть определён как отрезок другого скалярного типа посредством указания наибольшего и наименьшего значений отрезка. Первая константа задаёт нижнюю границу, которая не должна быть больше верхней.

  <ОТРЕЗОК ТИПА>::=<КОНСТАНТА>..<КОНСТАНТА>

Примеры:

   1..100
   -10..+10
   ПН..ПТ

4.2.2. Структурные типы

Структурный тип данных характеризуется типом (или типами) своих компонент и способом их организации.

  <СТРУКТУРНЫЙ ТИП>::=<ТИП МАССИВА> ! <ТИП ЗАПИСИ> !
                      <ТИП МНОЖЕСТВА> ! <ТИП ФАЙЛА>

Стандартный Паскаль содержит процедуры "PACK" и "UNPACK" для эффективной работы с компонентами структурного типа. В данном Паскале атрибут "PACKED", допустимый в стандарте, игнорируется, а использование процедур "PACK" и "UNPACK" недопустимо.

4.2.2.1. Типы массивов

Тип массива - это структура, состоящая из фиксированного числа компонент одного и того же типа, называемого типом компонент. Элементы массивов выбираются по индексам-значениям, принадлежащим к так называемому типу индексов. Определение типа массива задаёт как тип компонент, так и тип индексов:

  <ТИП МАССИВА>::=
  ARRAY[<ТИП ИНДЕКСА>(*,<ТИП ИНДЕКСА>*)] OF <ТИП КОМПОНЕНТ>
  <ТИП ИНДЕКСА>::=<ПРОСТОЙ ТИП>
  <ТИП КОМПОНЕНТ>::=<ТИП>

Если задано N типов индексов, то тип массива называется N-мерным; его компоненты выбираются с помощью N индексов.

Примеры:

  ARRAY[1..100] OF REAL
  ARRAY[1..10,1..20] OF 0..99
  ARRAY[BOOLEAN] OF ЦВЕТ
4.2.2.2. Типы записей

Тип записи - это структура, состоящая из фиксированного числа компонент, возможно, разных типов. Определение типа записи задаёт для каждой компоненты, называемой полем, её тип и обозначающий это поле идентификатор. Областью определённости этих идентификаторов поля является само определение записи, однако они доступны также в выборках поля, ссылающихся на переменную-запись данного типа.

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

  <ТИП ЗАПИСИ>::=RECORD<СПИСОК ПОЛЕЙ>END
  <СПИСОК ПОЛЕЙ>::=<ОБЩАЯ ЧАСТЬ> !
                   <ОБЩАЯ ЧАСТЬ>;<ВАРИАНТНАЯ ЧАСТЬ> !
                   <ВАРИАНТНАЯ ЧАСТЬ>
  <ОБЩАЯ ЧАСТЬ>::=<СЕКЦИЯ ЗАПИСИ>(*;<СЕКЦИЯ ЗАПИСИ>*)
  <СЕКЦИЯ ЗАПИСИ>::=<ИДЕНТИФИКАТОР ПОЛЯ>(*,<ИДЕНТИФИКАТОР ПОЛЯ>*):<ТИП>
  <ВАРИАНТНАЯ ЧАСТЬ>::=CASE<ПОЛЕ ПРИЗНАКА>:
                       <ИДЕНТИФИКАТОР ТИПА> OF <ВАРИАНТ>(*;<ВАРИАНТ>*)
  <ВАРИАНТ>::=<СПИСОК МЕТОК ВЫБОРА>:(<СПИСОК ПОЛЕЙ>)!
              <СПИСОК МЕТОК ВЫБОРА>
  <СПИСОК МЕТОК ВЫБОРА>::=<МЕТКА ВЫБОРА>(*,<МЕТКА ВЫБОРА>*)
  <МЕТКА ВЫБОРА>::=<КОНСТАНТА БЕЗ ЗНАКА>
  <ПОЛЕ ПРИЗНАКА>::=<ИДЕНТИФИКАТОР> 

Примеры:

  RECORD ДЕНЬ:1..31;
         МЕС:1..12;
         ГОД:INTEGER
  END
 
  RECORD  ИМЯ,ФАМИЛИЯ:ALFA;
          ВОЗРАСТ:0..99;
          ЖЕНАТ:BOOLEAN
  END
 
  RECORD  X,Y:REAL;
          ПЛОЩАДЬ:REAL;
     CASE Ф: ФОРМА OF
     ТРЕУГОЛЬНИК:   (СТОРОНА:REAL;
                     НАКЛОН,УГОЛ1,УГОЛ2:УГОЛ);
     ПРЯМОУГОЛЬНИК:(СТОРОНА1,СТОРОНА2:REAL;
                    СКЛОН,УГОЛ3:УГОЛ);
     КРУГ:(ДИАМЕТР:REAL)
  END
4.2.2.3. Типы множеств

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

+  объединение

*  пересечение

-  разность множеств (бинарное дополнение)

IN  отношение принадлежности (членства)

  <ТИП МНОЖЕСТВА>::=SET OF <ТИП БАЗЫ>
  <ТИП БАЗЫ>::=<ПРОСТОЙ ТИП> 

В Паскале, реализованном для ДВК, число элементов множества не может превышать 64. Определено стандартное множество "SET OF CHAR", что эквивалентно "SET OF SPACE..UNDERLINE", где SPACE = CHR(40B) и UNDERLINE = CHR(137B). Таким образом, "SET OF CHAR" не включает букв кириллицы и управляющих знаков, имеющих коды менее 40 (восьмеричное).

4.2.2.4. Типы файлов

Определение типа файла задаёт структуру, состоящую из последовательности однотипных компонент. Число компонент, называемое длиной файла, определением типа файла не фиксируется. Файл, имеющий ноль компонент, называется пустым; файлы, тип компонент которых литерный, называются текстовыми файлами.

<ТИП ФАЙЛА>::=FILE OF <ТИП>

Следующий тип является стандартным:

TYPE TEXT = FILE OF CHAR

Данный Паскаль не позволяет использовать файлы файлов, однако, можно применять массивы файлов, а также записи, содержащие в качестве компонентов файлы.

4.2.3. Типы указателей

Доступ к описанным в программе переменным можно получить через их идентификаторы. Они существуют всё время, пока выполняется процедура (область определённости), в которой эти переменные локальны, в связи с чем последние называются статическими или статически размещаемыми. С другой стороны, переменные могут создаваться и динамически, т.е. без всякой связи со структурой программы. Эти динамические переменные создаются стандартной процедурой "NEW"; поскольку они не входят в явные описания переменных, они не могут быть обозначены именем. Доступ к таким переменным осуществляется через указательные значения (ссылки), выдаваемые после создания динамической переменной. Каждый тип указателей состоит, таким образом, из неограниченного множества указывающих на однотипные элементы значений. Над указателями не определено никаких операций, кроме проверки на равенство. Значение "NIL" принадлежит всем типам указателей, но оно не указывает ни на какой элемент.

<ТИП УКАЗАТЕЛЯ>::=^<ИДЕНТИФИКАТОР ТИПА>

Примеры определений типов:

  ЦВЕТ = (КРАСН, ОРАНЖ, ЖЁЛТ, ЗЕЛ, ГОЛУБОЙ, СИНИЙ, ФИОЛ)
  ПОЛ = (МУЖ,ЖЕН)
  TEXT = FILE OF CHAR
  ФОРМА = (ТРЕУГОЛЬНИК,ПРЯМОУГОЛЬНИК,КРУГ)
  КАРТА = ARRAY[1..80] OF CHAR
  ALFA = ARRAY[1..ALFALENG] OF CHAR
  КОМПЛ = RECORD RE, IM: REAL END
  ЛИЦО = RECORD ФАМИЛИЯ,ИМЯ:ALFA;
         ВОЗРАСТ:INTEGER;
         ЖЕНАТ:BOOLEAN;
         ОТЕЦ,РЕБЁНОК,БРАТ:^ЛИЦО;
  CASE РОД: ПОЛ OF
       МУЖ: (ВОЕННООБЯЗАН,ЛЫС:BOOLEAN);
       ЖЕН: (БЕРЕМ:BOOLEAN;
            МЕРКА:ARRAY[1..3] OF INTEGER)
  END

4.3. Описание и изображение переменных

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

  <ОПИСАНИЕ ПЕРЕМЕННОЙ>::=<ИДЕНТИФИКАТОР>(*,<ИДЕНТИФИКАТОР>*):<ТИП>

Каждое описание переменной - файла "Ф" с компонентами типа "T" подразумевает дополнительное описание так называемой буферной переменной типа "T". Эта буферная переменная изображается Ф^ и служит для присоединения к файлу компонент при его заполнении и для получения доступа к файлу при чтении.

В отдельных случаях бывает удобно иметь возможность обращаться к абсолютным ячейкам памяти, например, к регистрам внешних устройств или таблицам операционной системы. Для этой цели в данном Паскале следует использовать ключевое слово ORIGIN в объявлении переменной. Например, следующая программа считывает знак с клавиатуры системного терминала на физическом уровне:

         CONST   READY   = 200B;
         VAR     KBCSR ORIGIN 177560B,
                 KBDAT ORIGIN 177562B:   INTEGER;
                 CH:CHAR;
         BEGIN
                 WHILE (KBCSR AND READY) = 0 DO; (*ЖДАТЬ*)
                 CH := CHR(KBDAТ);
         END.
 

Примеры:

 
  X, Y, Z: REAL
  U, V: КОМПЛ
  I, J: INTEGER
  K: 0..9
  P, Q: BOOLEAN
  ОПЕРАЦИЯ: (ПЛЮС, МИНУС, УМНОЖ)
  A: ARRAY [0..63] OF REAL
  B: ARRAY [ЦВЕТ, BOOLEAN] OF КОМПЛ
  Ц: ЦВЕТ
  F: FILE OF CHAR
  ОТТЕНОК1, ОТТЕНОК2: SET OF ЦВЕТ
  P1, P2: ^ЛИЦО

Изображения переменных обозначают либо полную переменную, либо некоторую компоненту переменной, либо переменную, на которую ссылается некоторый указатель. Предполагается, что переменные в последующих примерах описаны, как указано выше.

  <ПЕРЕМЕННАЯ>::= <ПОЛНАЯ ПЕРЕМЕННАЯ> ! <КОМПОНЕНТНАЯ ПЕРЕМЕННАЯ> !
                  <УКАЗУЕМАЯ ПЕРЕМЕННАЯ>

4.3.1. Полные переменные

Полная переменная изображается своим идентификатором:

  <ПОЛНАЯ ПЕРЕМЕННАЯ>::= <ИДЕНТИФИКАТОР ПЕРЕМЕННОЙ>
  <ИДЕНТИФИКАТОР ПЕРЕМЕННОЙ>::= <ИДЕНТИФИКАТОР>

4.3.2. Компонентные переменные

Компонентная переменная изображается соответствующей переменной, за которой следует задающий нужную компонент ту селектор. Форма селектора зависит от способа организации типа переменной:

  <КОМПОНЕНТНАЯ ПЕРЕМЕННАЯ>::= <ПЕРЕМЕННАЯ С ИНДЕКСАМИ> !
                               <УКАЗАТЕЛЬ ПОЛЯ> ! <БУФЕР ФАЙЛА>
4.3.2.1. Переменные с индексами

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

  <ПЕРЕМЕННАЯ С ИНДЕКСОМ>::=<ПЕРЕМЕННАЯ-МАССИВ>[<ВЫРАЖЕНИЕ>(*,<ВЫРАЖЕНИЕ>*)]
  <ПЕРЕМЕННАЯ-МАССИВ>::= <ПЕРЕМЕННАЯ>

Типы индексных выражений должны соответствовать типам индексов в описании соответствующего типа массива.

Примеры:

  A [12]
  A [I+J]
  B [КРАСН,TRUE]
  B [SUCC(Ц),P AND Q]
4.3.2.2. Указатели полей

Компонента переменной - записи обозначается через соответствующую переменную - запись, за которой следует идентификатор поля нужной компоненты:

  <УКАЗАТЕЛЬ ПОЛЯ>::= <ПЕРЕМЕННАЯ-ЗАПИСЬ>.<ИДЕНТИФИКАТОР ПОЛЯ>
  <ПЕРЕМЕННАЯ-ЗАПИСЬ>::= <ПЕРЕМЕННАЯ>
  <ИДЕНТИФИКАТОР ПОЛЯ>::= <ИДЕНТИФИКАТОР>

Примеры:

  U.RE
  B [КРАСН, TRUE].IM
  P2^.МЕРКА
4.3.2.3. Буферы файлов

В любой момент непосредственно доступна только одна компонента, определяемая текущей позицией файла (например, головкой считывания - записи). Эта компонента называется текущей компонентой файла; она представляется переменной, называемой буфером файла:

  <БУФЕР ФАЙЛА>::= <ПЕРЕМЕННАЯ-ФАЙЛ>
  <ПЕРЕМЕННАЯ-ФАЙЛ>::= <ПЕРЕМЕННАЯ>

4.3.3. Указуемые переменные

  <УКАЗУЕМАЯ ПЕРЕМЕННАЯ>::= <ПЕРЕМЕННАЯ-УКАЗАТЕЛЬ>^
  <ПЕРЕМЕННАЯ-УКАЗАТЕЛЬ>::= <ПЕРЕМЕННАЯ>

Если "P" является переменной-указателем, закреплённой за типом "T", то "P" обозначает эту переменную и её указательное значение, тогда как Р^ обозначает переменную типа "T", на которую ссылается "P";

Примеры:

  P1^.ОТЕЦ
  P1^.БРАТ^.РЕБЁНОК

5. ВЫРАЖЕНИЯ

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

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

<МНОЖИТЕЛЬ> ::= <ПЕРЕМЕННАЯ> ! <КОНСТАНТА БЕЗ ЗНАКА> !
                <ОБРАЩЕНИЕ К ФУНКЦИИ> ! <МНОЖЕСТВО>(<ВЫРАЖЕНИЕ>) !
                NOT<МНОЖИТЕЛЬ>
<МНОЖЕСТВО> ::= [<ВЫРАЖЕНИЕ>(*, <ВЫРАЖЕНИЕ> *)] ! [ ]
<ТЕРМ> ::= <МНОЖИТЕЛЬ> ! <ТЕРМ><ЗНАК ОПЕРАЦИИ ТИПА УМНОЖЕНИЯ><МНОЖИТЕЛЬ>
<ПРОСТОЕ ВЫРАЖЕНИЕ> ::= <ТЕРМ> ! 
                        <ПРОСТОЕ ВЫРАЖЕНИЕ><ЗНАК ОПЕРАЦИИ ТИПА СЛОЖЕНИЯ><ТЕРМ> !
                        <ЗНАК ОПЕРАЦИИ ТИПА СЛОЖЕНИЯ><ТЕРМ>
<ВЫРАЖЕНИЕ> ::= <ПРОСТОЕ ВЫРАЖЕНИЕ> !
                <ПРОСТОЕ ВЫРАЖЕНИЕ><ЗНАК ОТНОШЕНИЯ><ПРОСТОЕ ВЫРАЖЕНИЕ>

Выражения, являющиеся элементами множества, должны быть одного и того же типа, являющегося типом базы данного множества. "[ ]" обозначает пустое множество. Примеры:

  МНОЖИТЕЛИ:             X
                         15
                         (X+Y+Z)
                         SIN(X+Y)
                         [КРАСН, Ц, ЗЕЛ]
                         ^Р
  ТЕРМЫ:                 X*Y
                         I/(1-I)
                         P AND Q
                         (X<=Y) AND (Y<Z)
  ПРОСТЫЕ ВЫРАЖЕНИЯ:     X+Y
                         -X
                         ОТТЕНОК1 OR ОТТЕНОК2
                         I*J+1
  ВЫРАЖЕНИЯ:             X=15
                         Ц IN ОТТЕНОК1
 

5.1. Операция отрицания

Знак операции "NOT", применимый к операнду логического типа, обозначает отрицание.

5.2. Операции типа умножения

  <ЗНАК ОПЕРАЦИИ ТИПА УМНОЖЕНИЯ>::= *!/!DIV!MOD!AND
Таблица 1

Знак операции

Операция

Тип операндов

Тип результата

*

Умножение

REAL, INTEGER

INTEGER, если оба операнда имеют этот тип, REAL в остальных случаях

*

Пересечение множеств

Любой тип множеств Т

Т

/

Деление

REAL, INTEGER

REAL

DIV

Деление нацело (с усечением)

INTEGER

INTEGER

MOD

Нахождение остатка от деления нацело

AND

Конъюнкция

BOOLEAN

BOOLEAN

5.3. Операции типа сложения

  <ЗНАК ОПЕРАЦИИ ТИПА СЛОЖЕНИЯ> ::= ! + ! - ! OR
Таблица 2

Знак операции

Операция

Тип операндов

Тип результата

+

Объединение множеств

Любой тип множества Т

Т

+

Сложение

REAL, INTEGER

INTEGER, если оба операнда имеют этот тип, REAL в остальных случаях

-

Вычитание

REAL, INTEGER

-

Разность множеств

Любой тип множества Т

Т

OR

Дизъюнкция

BOOLEAN

BOOLEAN

 

Знаки операций "-" и "+", если они используются с одним и тем же операндом, обозначают соответственно изменение знака и тождественную операцию.

5.4. Логические операции с целыми числами

Булевские операции AND, OR и NOT имеют расширенную область действия и могут применяться для целых чисел. Операция будет выполняться над 16-ю разрядами операндов. Это расширение позволяет производить проверку и установку отдельных разрядов в целых переменных (например, для регистров внешних устройств).

Пример:

BYTE := ORD(CH) AND 377B;

5.5. Знаки отношений

  <ЗНАК ОТНОШЕНИЯ> ::= ! = ! <> ! < ! <= ! >= ! > ! IN
Таблица 3

Знак отношения

Тип операндов

Результат

=, <>

Любой тип, кроме типа файла

BOOLEAN

<, >, <=, >=

Любой скалярный тип или отрезок типа

BOOLEAN

IN

Любой скалярный тип или отрезок типа и связанный с ним соответствующий тип множеств

BOOLEAN

Заметим, что все скалярные типы определяют упорядоченные множества значений, в частности, FALSE<TRUE. Знаки отношений "<=" и ">=" можно использовать для сравнения значений типа множества, при этом они обозначают соответственно отношения включения.

Знаки отношений "<=", "<", ">", ">= " можно также применять к упакованным массивам литерного типа; в этом случае они обозначают алфавитное отношение порядка, соответствующее наличному множеству литер.

5.6. Указатели функции

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

  <УКАЗАТЕЛЬ ФУНКЦИИ> ::= <ИДЕНТИФИКАТОР ФУНКЦИИ> !
                    <ИДЕНТИФИКАТОР ФУНКЦИИ>(<ФАКТИЧЕСКИЙ
                     ПАРАМЕТР>(*, <ФАКТИЧЕСКИЙ ПАРАМЕТР> *))
  <ИДЕНТИФИКАТОР ФУНКЦИИ> ::= <ИДЕНТИФИКАТОР>

Примеры:

SUM(A,100)
SIN(X+Y)
EOF(F)
ORD(F^)

5.7. Адресный оператор "@"

В состав данного языка Паскаль входит унарный оператор, обозначаемый "@". Если его использовать с переменной типа "A", то результатом будет значение типа "^А" (указатель на "A"). Адресная операция может использоваться для работы со списковыми структурами данных или для передачи адресов в программы, написанные на языке МАКРОАССЕМБЛЕР. Например:

         TYPE    BLOCK=ARRAY[0..511] OF CHAR;
         VAR     BUFFER:BLOCK;
         BEGIN
                 (* ЗАПОМНИТЬ АДРЕС БУФЕРА *)
                 XRB.XRLOC:=@BUFFER
         END;
 

6. ОПЕРАТОРЫ

Операторы обозначают алгоритмические действия. Про них говорят, что они могут быть выполнены. Операторы могут быть снабжены меткой, к которой могут отсылать операторы перехода:

  <ОПЕРАТОР> ::= <НЕПОМЕЧЕННЫЙ ОПЕРАТОР> !
                 <МЕТКА>:<НЕПОМЕЧЕННЫЙ ОПЕРАТОР>
  <НЕПОМЕЧЕННЫЙ ОПЕРАТОР> ::= <ПРОСТОЙ ОПЕРАТОР> !
                             <СТРУКТУРНЫЙ ОПЕРАТОР>
  <МЕТКА> ::= <ЦЕЛОЕ БЕЗ ЗНАКА>

6.1. Простые операторы

Простые операторы - это операторы, никакая часть которых не содержит в себе других операторов.

  <ПРОСТОЙ ОПЕРАТОР> ::= <ОПЕРАТОР ПРИСВАИВАНИЯ> !
                         <ОПЕРАТОР ПРОЦЕДУРЫ> !
                         <ОПЕРАТОР ПЕРЕХОДА> !
                         <ПУСТОЙ ОПЕРАТОР>

6.1.1. Операторы присваивания

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

  <ОПЕРАТОР ПРИСВАИВАНИЯ> ::= <ПЕРЕМЕННАЯ> := <ВЫРАЖЕНИЕ> !
                              <ИДЕНТИФИКАТОР ФУНКЦИИ> := <ВЫРАЖЕНИЕ>

Переменная (соответственно функция) и выражение должно быть одного типа; допускаются следующие исключения:

  1. переменная имеет вещественный тип, а выражение - целый или его отрезок;
  2. тип выражения является отрезком типа соответствующей переменной или наоборот.

Примеры:

  X:=T+Z
  P:=(1<=I) AND (I<100)
  I:=SQR(K)-(I*J)
  ОТТЕНОК:=[ГОЛУБОЙ,SUCC(Ц)]

6.1.2. Операторы процедур

Оператор процедуры служит для выполнения процедуры, обозначенной идентификатором процедуры. Оператор процедуры может содержать список фактических параметров, подставляемых на место соответствующих им формальных параметров, определённых в описании процедуры. Соответствие устанавливается по позициям параметров в списках формальных и фактических параметров. Существует четыре вида параметров: так называемые параметры-значения, переменные, процедуры (соответствующий фактический параметр должен быть идентификатором процедуры) и параметры-функции (фактические параметры - идентификатор функции).

Стандартные процедуры и функции (оформленные в языке) не могут передаваться в качестве параметров. Это ограничение можно обойти путём определения второй процедуры, которая просто вызывает стандартную, например:

FUNCTION SINE(X:REAL): REAL;
BEGIN SINE:=SIN(X) END;

В случае параметров-значений фактический параметр должен быть выражением (в частности переменной). Если формальный параметр является локальной переменной вызываемой процедуры, то текущее значение выражения присваивается этой переменной в качестве её начального значения. В случае параметров-переменных фактическим параметром должна быть переменная. Соответствующий формальный параметр представляет эту фактическую переменную во всё время выполнения данной процедуры. Если эта переменная является компонентой некоторого массива, то её индекс вычисляется при вызове процедуры. Параметр-переменную следует использовать во всех случаях, когда параметр служит для представления результата процедуры:

  <ОПЕРАТОР ПРОЦЕДУРЫ>::= <ИДЕНТИФИКАТОР ПРОЦЕДУРЫ> !
           <ИДЕНТИФИКАТОР ПРОЦЕДУРЫ>(<ФАКТИЧЕСКИЙ ПАРАМЕТР>
           (*, <ФАКТИЧЕСКИЙ ПАРАМЕТР>*))
  <ИДЕНТИФИКАТОР ПРОЦЕДУРЫ>::=<ИДЕНТИФИКАТОР>
  <ФАКТИЧЕСКИЙ ПАРАМЕТР>::=<ВЫРАЖЕНИЕ> ! <ПЕРЕМЕННАЯ> !
                          <ИДЕНТИФИКАТОР ПРОЦЕДУРЫ> ! <ИДЕНТИФИКАТОР ФУНКЦИИ>

Примеры:

  TRANSPOSE(A,N,M)
  BTSECT(FST,-1.0,+1.0,X)

6.1.3. Операторы перехода

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

  <ОПЕРАТОР ПЕРЕХОДА>::=GOTO <МЕТКА>

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

  1. областью действия метки является описание процедуры, в пределах которой она определена. Таким образом, извне нельзя войти внутрь процедуры;
  2. если оператор перехода передаёт управление вовне процедуры, то его метка должна быть специфицирована описанием метки в заголовке процедуры, в которой эта метка определена.

6.1.4. Пустой оператор

Пустой оператор никак не обозначается и не вызывает никаких действий.

<ПУСТОЙ ОПЕРАТОР>::=

6.2. Структурные операторы

Структурные операторы являются конструкциями, составленными из других операторов, которые должны быть выполнены или последовательно (составной оператор), или повторно (циклы).

  <СТРУКТУРНЫЙ ОПЕРАТОР>::=<СОСТАВНОЙ ОПЕРАТОР> !
                     <УСЛОВНЫЙ ОПЕРАТОР> ! <ОПЕРАТОР ЦИКЛА>
                     <ОПЕРАТОР НАД ЗАПИСЬЮ>

6.2.1. Составные операторы

Составной оператор предписывает выполнение составляющих его операторов в порядке их написания. Символы BEGIN и END действуют как операторные скобки.

  <СОСТАВНОЙ ОПЕРАТОР>::=BEGIN<ОПЕРАТОР>(*;<ОПЕРАТОР>*)END

Пример:

      BEGIN Z:=X; X:=Y; Y:=Z END

6.2.2. Условные операторы

Условный оператор назначает к выполнению один из составляющих его операторов:

  <УСЛОВНЫЙ ОПЕРАТОР>::=<ОПЕРАТОР "IF">!
                       <ОПЕРАТОР "CASE">
6.2.2.1. Оператор "IF"

Оператор "IF" указывает, что некоторый оператор должен выполняться, если только некоторое условие (логическое выражение) истинно (TRUE). Если же оно имеет значение FALSE, то либо не выполняется никакой оператор, либо выполняется оператор, следующий за символом ELSE:

  <ОПЕРАТОР "IF">::=IF <ВЫРАЖЕНИЕ> THEN <ОПЕРАТОР> !
                   IF <ВЫРАЖЕНИЕ> THEN <ОПЕРАТОР> ELSE <ОПЕРАТОР>

Выражение между символами IF и THEN должно иметь логический тип.

ПРИМЕЧАНИЕ. Синтаксическая неоднозначность, возникающая в конструкции:

  IF <ВЫРАЖЕНИЕ1> THEN IF <ВЫРАЖЕНИЕ2> THEN <ОПЕРАТОР1>
                                       ELSE <ОПЕРАТОР2>

разрешается толкованием этой конструкции как эквивалента для:

  IF <ВЫРАЖЕНИЕ1>
  THEN BEGIN IF <ВЫРАЖЕНИЕ2>
             THEN <ОПЕРАТОР1>
             ELSE <ОПЕРАТОР2>
       END

Примеры:

    IF X=1.5 THEN Z:=X+Y ELSE Z:=1.5
   IF P1<>NIL THEN P1:=P1^.ОТЕЦ
6.2.2.2. Оператор "CASE"

Оператор "CASE" состоит из выражения (селектора) и списка операторов, каждый из которых помечен константой селекторного типа. Оператор "CASE" указывает, что должен быть выполнен один оператор: тот, метка которого равна текущему значению селектора. Если ни одна из меток в операторе CASE не совпадает со значением "селекторной" переменной, то выполняется последовательность операторов, следующая за символом ELSE. Использование ";" недопустимо между ELSE и END в операторе CASE:

  <ОПЕРАТОР "CASE">::=CASE<ВЫРАЖЕНИЕ> OF
                <АЛЬТЕРНАТИВА> (*;<АЛЬТЕРНАТИВА>*)
               [ELSE <ОПЕРАТОР>] END
  <АЛЬТЕРНАТИВА>::=<СПИСОК МЕТОК ВЫБОРА>:<ОПЕРАТОР>
  <СПИСОК МЕТОК ВЫБОРА>::=<МЕТКА ВЫБОРА>(*,<МЕТКА ВЫБОРА>*)

Примеры:

  CASE ОПЕРАЦИЯ OF                   CASE I OF
       ПЛЮС:X:=X+Y;                         1:X:=SIN(X);
       МИНУС:X:=X-Y;                        2:X:=COS(X);
       УМНОЖ:X:=X*Y;                        3:X:=EXP(X);
 END                                        4:X:=LN(X);
                                    END
 
         REPEAT
                 READLN(CH);
                 CASE CH OF
                         'A':APPEND;
                         'D':DELETE;
                         'I':INSERT;
                         'N':NEWFILE;
                         'Q':;
                         ELSE
                          WRITELN('"',CH,'" IS NOT LEGAL')
                 END;
         UNTIL CH = 'Q';

6.2.3. Циклы

Операторы цикла предписывают многократное выполнение некоторых операторов. Если число повторений известно заранее, т.е. до начала выполнения цикла, то подходящей конструкцией является оператор "FOR"; в остальных случаях следует использовать оператор "WHILE" или оператор "REPEAT"

  <ОПЕРАТОР ЦИКЛА>::=<ОПЕРАТОР "WHILE"> !
                     <ОПЕРАТОР "REPEAT"> ! <ОПЕРАТОР "FOR">
6.2.3.1. Оператор "WHILE"
  <ОПЕРАТОР "WHILE">::=WHILE <ВЫРАЖЕНИЕ> DO <ОПЕРАТОР>

Выражение, управляющее повторениями, должно иметь логический тип. Оператор повторно используется до тех пор, пока значением выражения не станет "FALSE". Если значение выражения с самого начала "FALSE", то оператор не выполняется.

Оператор "WHILE":

WHILE E DO S

эквивалентен конструкции:

      IF E THEN
         BEGIN S;
            WHILE E DO S
         END

Примеры:

   WHILE A(I) <> X DO I:=I+1
 
   WHILE I>0 DO
   BEGIN IF ODD(I) THEN Z:=Z*X;
        I:=IDIV2;
        X:=SQR(X)
   END
 
   WHILE NOT EOF(F) DO
   BEGIN P(F^); GET(F)
   END
6.2.3.2. Оператор "REPEAT"
  <ОПЕРАТОР "REPEAT">::=
    REPEAT <ОПЕРАТОР>(*,<ОПЕРАТОР>*) UNTIL <ВЫРАЖЕНИЕ>

Выражение, управляющее повторениями, должно иметь логический тип. Последовательность операторов между REPEAT и UNTIL выполняется повторно (и не менее одного раза до тех пор, пока значением соответствующего выражения не станет TRUE.

Оператор "REPEAT":

REPEAT S UNTIL Е

эквивалентен оператору:

    BEGIN S;
    IF NOT E THEN
        REPEAT S UNTIL E
    END

Примеры:

  REPEAT K:=I MOD J;
         I:=J;
         J:=K;
  UNTIL J=0
 
  REPEAT P(F);GET(F)
  UNTIL EOF(F)
6.2.3.3. Оператор "FOR"

Оператор "FOR" предписывает повторное выполнение соответствующего оператора по мере присваивания переменной, называемой параметром цикла, некоторой последовательности значений.

  <ОПЕРАТОР "FOR">::=FOR <ПАРАМЕТР ЦИКЛА>:=<СПИСОК ЦИКЛА> DO <ОПЕРАТОР>
  <СПИСОК ЦИКЛА>::=<ПЕРВОЕ ЗНАЧЕНИЕ> TO <ПОСЛЕДНЕЕ ЗНАЧЕНИЕ> !
                   <ПЕРВОЕ ЗНАЧЕНИЕ> DOWNTO <ПОСЛЕДНЕЕ ЗНАЧЕНИЕ>
  <ПАРАМЕТР ЦИКЛА>::=<ИДЕНТИФИКАТОР>
  <ПЕРВОЕ ЗНАЧЕНИЕ>::=<ВЫРАЖЕНИЕ>
  <ПОСЛЕДНЕЕ ЗНАЧЕНИЕ>::=<ВЫРАЖЕНИЕ>

Параметры цикла, первое значение и последнее значение должны быть одного и того же скалярного типа (или его отрезка) и не должны меняться повторяемым в цикле оператором.

Цикл с параметром вида:

FOR V:= E1 TO E2 DO S

эквивалентен последовательности операторов:

V:=E1; S; V:=SUCC(V); S;...; V:=E2; S;

а цикл с параметром вида:

FOR V: = E1 DOWNTO E2 DO S

эквивалентен последовательности операторов:

V:=E1; S; V:=PRED(V); S;...; V:=E2; S;

ПРИМЕЧАНИЕ. Последнее значение параметра остаётся неопределённым после завершения цикла.

Примеры:

  FOR I:=2 TO 100 DO IF A[I]>MAX THEN MAX:=A(I)
  FOR I:=1 TO N DO
    FOR J:=1 TO N DO
    BEGIN X:=0;
      FOR K:=1 TO N DO X:=X+A(I,J)*B(K,J)
      C[I,J]:=X
    END
  FOR Ц := КРАСН TO ГОЛУБОЙ DO Q(Ц)
6.2.3.4. Оператор EXIT

Оператор EXIT используется для выхода из тела одного из итерационных операторов (WHILE, REPEAT, FOR). Например, поиск по таблице:

         FOUND := FALSE;
         FOR I := 1 TO TABLESIZE DO
                 IF TABLE[I] = KEY
                    THEN BEGIN FOUND := TRUE; EXIT END;

6.2.4. Оператор над записями "WITH"

  <ОПЕРАТОР "WITH"> ::= WITH <СПИСОК ПЕРЕМЕННЫХ-ЗАПИСЕЙ>
                          DO <ОПЕРАТОР>
  <СПИСОК ПЕРЕМЕННЫХ-ЗАПИСЕЙ> ::= <ПЕРЕМЕННАЯ ЗАПИСЬ>
                                (*,<ПЕРЕМЕННАЯ ЗАПИСЬ>*)

В пределах внутреннего оператора в операторе "WITH" компоненты (поля) переменной-записи, заданной в его заголовке, могут обозначаться одним только своим идентификатором поля, т.е. без предшествующего им написания полной переменной записи. Фактически операторы над записями расширяют область определённости идентификаторов поля заданной переменной-записи, так что идентификаторы поля могут выступать, как идентификаторы переменных.

Пример:

  WITH DATA DO
  IF MEC = 12 THEN
  BEGIN MEC := 1; ГОД := ГОД + 1
  END
  ELSE MEC := MEC + 1

Этот оператор эквивалентен следующему:

  IF DATA.MEC = 12 THEN
  BEGIN DАТАЕC := 1; DАТА.ГОД:=DАТА.ГОД + 1
  END
  ELSE DАТА.МЕС:= DАТА.МЕС + 1

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

Оператор "WITH" может иметь уровень вложенности не выше 4-x; если сложные выражения используются внутри этого оператора, то уровень вложенности может быть не более 2-х или 3-x.

7. ОПИСАНИЕ ПРОЦЕДУР

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

  <ОПИСАНИЕ ПРОЦЕДУРЫ>::=<ЗАГОЛОВОК ПРОЦЕДУРЫ>
                       <РАЗДЕЛ ОПИСАНИЙ МЕТОК>/
                       <РАЗДЕЛ ОПРЕДЕЛЕНИЙ КОНСТАНТ>/
                       <РАЗДЕЛ ОПРЕДЕЛЕНИЙ ТИПОВ>/
                       <РАЗДЕЛ ОПИСАНИЙ ПЕРЕМЕННЫХ>/
                       <РАЗДЕЛ ОПИСАНИЙ ПРОЦЕДУР И ФУНКЦИЙ>/
                       <РАЗДЕЛ ОПЕРАТОРОВ>

Заголовок процедуры задаёт идентификатор, именующий процедуру, и идентификаторы формальных параметров (если они есть). Параметрами могут быть параметры-переменные, -значения, -процедуры или параметры-функции.

  <ЗАГОЛОВОК ПРОЦЕДУРЫ>::=PROCEDURE<ИДЕНТИФИКАТОР>; !
                PROCEDURE<ИДЕНТИФИКАТОР>(<СЕКЦИЯ ФОРМАЛЬНЫХ ПАРАМЕТРОВ>
                                        (*;<СЕКЦИЯ ФОРМАЛЬНЫХ ПАРАМЕТРОВ*));
  <СЕКЦИЯ ФОРМАЛЬНЫХ ПАРАМЕТРОВ>::=<ГРУППА ПАРАМЕТРОВ> !
                               VAR <ГРУППА ПАРАМЕТРОВ> !
                          FUNCTION <ГРУППА ПАРАМЕТРОВ> !
                         PROCEDURE <ИДЕНТИФИКАТОР>(*;<ИДЕНТИФИКАТОР>*)
  <ГРУППА ПАРАМЕТРОВ>::=<ИДЕНТИФИКАТОР>
                        (*,<ИДЕНТИФИКАТОР>*):<ИДЕНТИФИКАТОР ТИПА>

Группы параметров без предшествующего спецификатора считаются параметрами-значениями.

Раздел описаний меток специфицирует все метки, локализованные в данной процедуре:

  <РАЗДЕЛ ОПИСАНИЙ МЕТОК>::=<ПУСТО> ! LABEL <МЕТКА>(*,<МЕТКА>*);
 
  <РАЗДЕЛ ОПРЕДЕЛЕНИЙ КОНСТАНТ>::=<ПУСТО> !
         CONST <ОПРЕДЕЛЕНИЕ КОНСТАНТЫ>(*;<ОПРЕДЕЛЕНИЕ КОНСТАНТЫ>*);
 
  <РАЗДЕЛ ОПРЕДЕЛЕНИЙ ТИПОВ>::=<ПУСТО> !
         TYPE <ОПРЕДЕЛЕНИЕ ТИПА>(*;<ОПРЕДЕЛЕНИЕ ТИПА>*);
 
  <РАЗДЕЛ ОПИСАНИЙ ПЕРЕМЕННЫХ>::=<ПУСТО> !
         VAR <ОПИСАНИЕ ПЕРЕМЕННОЙ>(*;<ОПИСАНИЕ ПЕРЕМЕННОЙ>*);
 
  <РАЗДЕЛ ОПИСАНИЙ ПРОЦЕДУР И ФУНКЦИЙ>::=(*<ОПИСАНИЕ ПРОЦЕДУРЫ ИЛИ ФУНКЦИИ>;*)
  <ОПИСАНИЕ ПРОЦЕДУРЫ ИЛИ ФУНКЦИИ>::=<ОПИСАНИЕ ПРОЦЕДУРЫ> !
                                     <ОПИСАНИЕ ФУНКЦИИ>

Раздел операторов задаёт алгоритмические действия, которые должны быть выполнены после обращения к процедуре с помощью оператора процедуры:

  <РАЗДЕЛ ОПЕРАТОРОВ>::=<СОСТАВНОЙ ОПЕРАТОР>

Все идентификаторы, введённые в разделе формальных параметров, разделе определений констант, типов, разделе описаний переменных и процедур или функций, локальны в данном описании процедуры, которое называется областью определённости этих идентификаторов. Они не доступны вне своей области определённости. Значения локальных переменных в момент входа в тело не определены. Использование в теле процедуры её собственного имени подразумевает рекурсивное выполнение этой процедуры.

Синтаксически вложенность процедур не может быть более 10-ти. При выполнении на вложенность не накладывается ограничений, но большая вложенность при рекурсии может привести к исчерпыванию рабочей памяти.

Примеры описаний процедур:

  PROCEDURE BISECT(FUNCTION F:REAL; A,B:REAL; VAR Z:REAL);
    VAR M :REAL;
   BEGIN (* ПРЕДПОЛАГАЕТСЯ ЧТО F(A)<0 И F(B)>0 *)
     WHILE ABS(A-B) > 1E-10*ABS(A) DO
     BEGIN M := (A+B)/2.0;
       IF F(M)<0 THEN A := M ELSE B := M
     END;
     Z:=M
   END

Процедура (функция) может быть вызвана раньше, чем она определена, если есть ссылка "Вперёд" - FORWARD. Список параметров и тип окончательного результата записывается только в FORWARD ссылке, например:

  PROCEDURE Q(X:T); FORWARD;
  PROCEDURE P(Y:T);
     BEGIN Q(A) END;
  PROCEDURE Q;  (*ПАРАМЕТРЫ НЕ ПОВТОРЯЮТСЯ*)
     BEGIN P(B) END;
  BEGIN P(A);Q(B)
  END.

7.1. Стандартные процедуры

Предполагается, что стандартные процедуры заранее описаны в любой реализации языка Паскаль. Любая реализация может дополнительно вводить такие заранее описанные процедуры. Поскольку они, как и все стандартные величины, считаются описанными в области определённости, охватывающей всю программу, написанную на Паскале, то появление в этой программе описаний, переопределяющих эти идентификаторы, не приводит к конфликтам. Стандартные процедуры перечислены и объяснены ниже.

7.1.1. Процедуры работы с файлами

PUT(F)

присоединяет значение буферной переменной F^ к файлу "F". Определено только в случае, когда перед исполнением значение предиката EOF(F) есть TRUE; EOF(F) сохраняет значение TRUE, значение же F^ становится неопределённым;

GET(F)

смещает текущую позицию файла (головку чтения-записи) на следующую компоненту и приписывает значение этой компоненты буферной переменной F^. Если следующей компоненты не существует, то значением EOF(F) становится TRUE, а значение F^ не определено. Результат GET (F) определён только тогда, когда перед исполнением соответствующего вызова EOF (F) =FALSE;

RESET(F)

возвращает текущую позицию файла в начала файла и приписывает буферной переменной F^ значение первого элемента "F". Значением EOF (F) становится FALSE, если "F" не пуст; в противном случае F^ не определено, а значением EOF(F) остаётся TRUE;

REWRITE(F)

уничтожает текущее значение "F", так что может начаться заполнение нового файла; EOF(F) принимает значение TRUE;

BREAK(F)

вызывает немедленный вывод, возможно, ещё неполного буфера (блока) в файл. Это надо использовать при работе с терминалом, например, для вывода подсказки или сообщения. Следует отметить, что данный Паскаль не буферизует работу с драйверами, о которых известно, что они являются "интерактивными", такими как выходной файл по умолчанию.

Пример:

         VAR F:TEXT;
         BEGIN
           REWRITE(F,'TT:');
           WRITELN(F,'ВВЕДИТЕ КОМАНДНУЮ СТРОКУ');
           BREAK(F);    (* ВЫВЕСТИ ДАННЫЕ НА ТТ: *)
         END.

CLOSE(F)

пересылает на внешнее устройство не до конца заполненный буфер, устраняет связь с внешним файлом и освобождает буферную память для использования её в других целях. Процедуры "RESET" или "REWRITE" должны предшествовать всякой работе с файловой переменной.

ПРИМЕЧАНИЕ. Процедура "CLOSE" всегда должна использоваться в конце работы с файлом, созданным программой (выходным файлом), иначе можно потерять последний буфер, который не будет записан в файл. Закрывание файлов для ввода не является обязательным, но позволяет освободить буферную память.

7.1.2. Дополнительные аргументы для "RESET" и "REWRITE"

В данной реализации расширены стандартные процедуры "RESET" и "REWRITE" тремя дополнительными параметрами для указания связи между внутренними файловыми переменными и файлами на внешних устройствах

  PROCEDURE RESET(F:FILE;NAME,DEFEXT:STRING;
                  VAR LEN:INTEGER)

Процедура RESET связывает файловую переменную с существующим внешним файлом, а также устанавливает указатель файла на первый элемент (запись). "F" всегда должна присутствовать и быть файловой переменной. Имя файла "NAME" и расширение имени файла должны иметь тип "ARRAY OF CHAR".

Имя файла должно соответствовать принятому в ФОДОС-2 стандартному обозначению и может включать имя и номер устройства, а также тип файла. Если во втором параметре отсутствует тип файла, то по умолчанию будет использован тип "DAT".

Переменная "LEN" получит значение, равное числу блоков по 512 байт в файле, либо -1, если файл не найден. Следует учесть, что если этот параметр не использован, то отсутствие файла приведёт к фатальной ошибке программы.

  PROCEDURE REWRITE(F:FILE; NAME,DEFEXT:STRING;
                    VAR LEN:INTEGER)

Процедура "REWRITE" создаёт новый файл на внешнем устройстве. Параметры "NAME" и "DEFEXT" имеют то же значение (смысл), что и для процедуры "RESET". Параметр "LEN" указывает размер создаваемого файла в блоках по 512 байт.

Пример:

         VAR NAME: ARRAY[1..20] OF CHAR;
             INF,OUTF: TEXT;
             (* ОПРЕДЕЛЕНО В СИСТЕМЕ КАК "FILE OF CHAR *)
             LEN: INTEGER;
         BEGIN
             (* СВЯЗАТЬ OUTF С УСТРОЙСТВОМ ПЕЧАТИ *)
             REWRITE(OUTF,'LP:');
             REPEAT
                 WRITE('FILENAME: ');
                 (* ЗАПРОСИТЬ ИМЯ ФАЙЛА С ТЕРМИНАЛА *)
                 READLN(NAME);
                 (*СВЯЗАТЬ INF С СУЩЕСТВУЮЩИМ ФАЙЛОМ *)
                 RESET(INF,NAME,'PAS',LEN)
             (* ПОВТОРЯТЬ ПОКА ФАЙЛ НЕ БУДЕТ ОТКРЫТ *)
             UNTIL LEN<>-1;
         END.

7.1.3. Процедура динамического размещения

NEW(P)

размещает новую переменную V и приписывает ссылку на V переменной - указателю Р;

DISPOSE(P)

освобождает память, занимаемую переменной P^;

Если тип V - это тип записи с вариантами, то в вызовах "NEW" и "DISPOSE" выделяется и освобождается максимальная область памяти, необходимая для записи.

NEW(P,T1,...,TN)

может быть использован для размещения конкретного варианта (в случае записи с вариантами) со значениями поля признака T1,...,TN. Это не означает назначения поля признака.

DISPOSE(P,T1,...,TN)

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

7.1.4. Файлы прямого доступа

Предлагаемая реализация Паскаля содержит несколько определений процедур, которые после трансляции вместе с программой обеспечивают прямой доступ к элементам файловой переменной.

   PROCEDURE SEEK(VAR F:RANFIL; VAR DATA:USERTYPE;
                  N:INTEGER)

Процедура "SEEK" возвращает N-ый элемент файла "F" в переменной "DATA". Устанавливается EOF(F), если указанный элемент не существует.

   PROCEDURE DEPOSIT(VAR F:RANFIL; VAR DATA:USERTYPE;
                     N:INTEGER)

Процедура "DEPOSIT" заносит значение переменной "DATA" в файл "F" в качестве N-ого элемента (записи). При необходимости файл расширяется.

   PROCEDURE CLOSERANDOMFILE(VAR F:RANFIL)

Данная процедура должна использоваться для закрытия файла прямого доступа (вместо "CLOSE").

    TYPE USERTYPE=ARRAY[0..255] OF INTEGER;
 
    TYPE RANFIL=FILE OF USERTYPE;

Файл F открывается процедурой RESET, а создаётся процедурой REWRITE. При создании файла необходимо записать хотя бы один элемент.

7.2. Процедуры ввода/вывода

Стандартный Паскаль содержит определения двух файловых переменных "INPUT" и "OUTPUT", которые являются файлами по умолчанию для "READ" и "WRITE". Поэтому "READ(I)" эквивалентно "READ(INPUT,I)". В Паскале, реализованном для ДВК, переменные "INPUT" и "OUTPUT" предварительно не определены. В качестве файла по умолчанию используется терминал для процедур "READ" и "WRITE".

7.2.1. Процедура READ

Для процедуры READ действуют следующие обозначения: F - текстовый файл; V1,...,VN - параметры процедуры.

Стандартная процедура READ допускает произвольное число параметров, так что:

READ(F,V1,...,VN) означает READ(F,V1);...;READ(F,VN)

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

7.2.2. Процедура READLN

Стандартная процедура READLN пропускает во входном файле символы до тех пор, пока не встретится конец строки. READLN (F) работает также как:

      WHILE NOT EOLN(F) DO GET(F);
      GET(F)

READLN(F,V1,...,VN) означает READ(F,V1,...,VN);READLN(F)

7.2.3. Процедура WRITE

Для процедуры WRITE действуют следующие обозначения: F - текстовый файл; P1,...,PN - параметры процедуры; Е - выражение; M,N - выражения типа INTEGER (форматы вывода).

Стандартная процедура WRITE допускает произвольное число параметров, так что:

WRITE(F,P1,...,PN) означает WRITE(F,P1);...; WRITE(F,PN)

Каждый параметр принимает одну из следующих форм:

       E      E:M      E:M:N

Е может быть литерного, целого, вещественного или логического типа либо типа массив. Значения преобразуются в последовательность из М литер. Если величина Е для своего представления требует меньше символов, чем М, то добавляются пробелы, так что выводится точно М символов. Если М меньше, чем необходимо для вывода величины Е, то выводится столько символов, сколько требует Е для своего представления (М в этом случае игнорируется). N применимо только к параметрам, имеющим вещественное значение, и задаёт число цифр, печатаемых после десятичной точки. Если N опущено, то число печатается в форме с плавающей точкой. Если М опущено, то по умолчанию для разных типов назначаются следующие значения М:

Литерный

-

1

Целый

-

13

Вещественный

-

13

Логический

-

6

Процедура "WRITE" будет выводить целые числа в восьмеричном виде, если выражение для формата вывода будет отрицательным, например:

         (* ВЫВЕСТИ "I" В ВОСЬМ.ВИДЕ - 5 ЗНАКОВ *)
         WRITE(I:-5);

Пример:

     Пусть K=135, N=4, X=72.83, B=TRUE, C='A', тогда
     WRITE(K+K:N,X:12,X:6:1,"  A",C,B)

 Выводит последовательность литер

  270 7.2830E+01  72.8  AA  TRUE

7.2.4. Процедура WRITELN

Стандартная процедура WRITELN(F) используется, чтобы окончить выходную строку и начать новую. Она добавляет маркер конца строки к файлу F.

WRITELN(F,P1,...,PN) означает WRITE(F,P1,...,PN);WRITELN(F)

Имя файла в процедурах READ, READLN, WRITE, WRITELN можно опустить. По умолчанию в качестве файла используется терминал.

7.2.5. Ввод/вывод с терминала

Стандартный Паскаль требует, чтобы первый элемент файла был получен в программе непосредственно после работы процедуры "RESET" (Буферная переменная F^ получает это значение немедленно). Это приводит к сложностям, если в качестве файла используется терминал. Например, если входной файл по умолчанию является терминалом, то стандарт требует ввода первого знака или строки перед запуском программы на выполнение.

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

Это позволяет решить большинство из проблем с терминалом удовлетворительным образом, но следует понимать, что это порождает некоторые другие трудности, например:

         VAR LINE: ARRAY[1..72] OF CHAR;
             COUNT: INTEGER;
         BEGIN
             COUNT:=0;
             WHILE NOT EOLN DO BEGIN
                 COUNT:=COUNT+1;
                 READ(LINE[COUNT])
                 END;
             READLN
         END.

В приведённом примере показывается стандартная схема для чтения строки знаков с терминала. Когда этот способ применяется к интерактивному файлу, то невозможно отличить пустую строку и строку, содержащую один пробел. Это связано с тем, что "EOLN" не может быть установлен, пока не встретится знак конца строки для завершения запроса "READ".

7.3. Конец файла

В ФОДОС-2 файл представляется последовательностью блоков по 512 байт каждый. При этом в конце файла отсутствует признак конца файла. Поэтому функция "EOF" не всегда обеспечивает правильную индикацию конца файла. Решить эту проблему можно, используя счётчик записей в файле или путём использования символьной записи, которая будет выступать в качестве признака конца.

Данная проблема не относится к текстовым файлам, которые в качестве признака конца используют знак <СУ/Z>.

8. ОПИСАНИЯ ФУНКЦИИ

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

  <ОПИСАНИЕ ФУНКЦИИ>::=<ЗАГОЛОВОК ФУНКЦИИ>
                       <РАЗДЕЛ МЕТОК>/
                       <РАЗДЕЛ ОПРЕДЕЛЕНИЙ КОНСТАНТ>/
                       <РАЗДЕЛ ОПРЕДЕЛЕНИЙ ТИПОВ>/
                       <РАЗДЕЛ ОПИСАНИЙ ПЕРЕМЕННЫХ>/
                       <РАЗДЕЛ ОПИСАНИЙ ПРОЦЕДУР И ФУНКЦИЙ>/
                       <РАЗДЕЛ ОПЕРАТОРОВ>

Заголовок функции задаёт идентификатор, обозначающий данную функцию, формальные параметры функции и её тип:

  <ЗАГОЛОВОК ФУНКЦИИ>::=FUNCTION <ИДЕНТИФИКАТОР:<ТИП РЕЗУЛЬТАТА>; !
  FUNCTION <ИДЕНТИФИКАТОР>(<СЕКЦИЯ ФОРМАЛЬНЫХ ПАРАМЕТРОВ>
                         (*;СЕКЦИЯ ФОРМАЛЬНЫХ ПАРАМЕТРОВ>*)):<ТИП РЕЗУЛЬТАТА>
  <ТИП РЕЗУЛЬТАТА>::=<ИДЕНТИФИКАТОР ТИПА>

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

Вызов функции может быть раньше её описания, если есть FORWARD ссылка (см. п. 7).

Примеры:

  FUNCTION SQRT (X : REAL) : REAL;
    VAR X0,X1: REAL;
  BEGIN X1:=X; (*X > 1, МЕТОД НЬЮТОНА*)
    REPEAT X0:=X1; X1:=(X0 + X/X0) * 0.5
    UNTIL ABS(X1 - X0) < EPS*X1;
    SQRT:=X0
  END
 
  FUNCTION MAX(A : VECTOR; N : INTEGER) : REAL;
         VAR X : REAL; I : INTEGER;
  BEGIN X :=A[1];
         FOR I :=2 TO N DO
         BEGIN (* X=MAX(A[1]...A[I-1]) *)
         IF X<A[I] THEN X := A[I]
         END;
         (* X = MAX(A[1]...A[N]) *)
         MAX:=X
  END
 
  FUNCTION СТЕПЕНЬ (X:REAL; Y:INTEGER) :REAL; (* Y>=0 *)
         VAR W,Z ; REAL;I : INTEGER;
  BEGIN W =: X; Z := 1; I := Y;
         WHILE I <> 0 DO
         BEGIN (* Z * W**I = X**Y *)
         IF ODD(I) THEN Z := Z*W;
         I := I DIV 2; W := SQR(W)
  END (* Z = X**Y *);
  СТЕПЕНЬ := Z
  END

8.1. Стандартные функции

Предполагается, что стандартные функции заранее описаны в любой реализации языка Паскаль. Любая реализация может вводить дополнительно такие заранее описанные функции.

Ниже следует список стандартных функций с пояснениями.

8.1.1. Арифметические функции

ABS (X)

вычисляет абсолютную величину X. Тип X должен быть вещественным или целым, тип результата совпадает с типом X;

SQR(X)

вычисляет X во 2-й степени. Тип X должен быть вещественным или целым, тип результата совпадает с типом X;

SIN(X)

COS(X)

EXP(X)

LN(X)

SQRT(X)

ARCTAN(X)

Тип X должен быть вещественным или целым; результат имеет вещественный  тип.

EXP10(X)

LOG(X)

аналогично EXP(X) и LN(X), но по основанию 10;

 

8.1.2. Предикаты

ODD(X)

тип X должен быть целым, результат равен TRUE, если X - число нечётное, т.е. "X MOD 2 = 1";

EOF(F)

указывает, находится ли файл "F" в состоянии "конец файла".

8.1.3. Функции преобразования

TRUNC(X)

X должен быть вещественного типа, результат имеет тип целый (INTEGER) и получается при отбрасывании дробной части X, т.е. если X>=0, то X-1<TRUNC(X)<=X; если X<0, то X+1 >TRUNC (X) >=X;

ROUND(X)

X должен быть вещественного типа, результат (целого типа) - целое число, ближайшее к X, т.е.: ROUND (X) =TRUNC (X+0.5) для X>=0; и TRUNC(X-0.5) для X<0;

ORD(X)

X должен быть литерного типа, результат (целого типа) - это порядковый номер литеры X в заданной последовательности литер. Результат ORD(X) будет в диапазоне (-128..127).

CHR(X)

X должен быть целого типа, результат (литерного типа) - это литера, порядковый номер которой равен X.

8.1.4. Функция "TIME"

Функция "TIME" возвращает значение типа REAL, соответствующее времени дня в часах после полуночи. Точность этой функции не менее одной секунды, например:

     PROCEDURE WRITETIME;
     VAR R:REAL;
             HOURS,MINUTES:INTEGER;
             AMPM: ARRAY [1..2] OF CHAR;
     BEGIN
       R:=TIME;
       HOURS:=TRUNC(TIME);
       MINUTES:=TRUNC((R-HOURS)*60.0);
       IF HOURS > 12
             THEN AMPM:='PM'
             ELSE IF (HOURS = 12) AND (MINUTES = 0)
               THEN AMPM:='M '
               ELSE AMPM:='AM';
       WRITE('AT THE TONE THE TIME WILL BE: ');
       WRITE((HOURS+11) MOD 12 + 1 :2);
       WRITE(':', MINUTES DIV 10:1,
                  MINUTES MOD 10:1, AMPM:3);
       WRITE(CHR(7));
     END.

8.1.5. Прочие стандартные функции

SUCC(X)

X может быть любого скалярного типа или отрезком типа; результат - это значение, следующее за X (если таковое имеется);

PRED(X)

X может быть любого скалярного типа или отрезком типа, результат - это значение, предшествующее X (если оно существует).

9. ПРОГРАММЫ

Программа на языке Паскаль имеет вид описания процедуры без заголовка. Если заголовок всё же указан, то он будет распечатываться в начале каждой страницы листинга программы. Любой параметр в заголовке программы игнорируется.

  <ПРОГРАММА> :: = <РАЗДЕЛ ОПИСАНИЙ МЕТОК>/
                   <РАЗДЕЛ ОПРЕДЕЛЕНИЙ КОНСТАНТ>/
                   <РАЗДЕЛ ОПРЕДЕЛЕНИЙ ТИПОВ>/
                   <РАЗДЕЛ ОПИСАНИЙ ПЕРЕМЕННЫХ>/
                   <РАЗДЕЛ ОПИСАНИЙ ПЕРЕМЕННЫХ И ФУНКЦИЙ>/
                   <РАЗДЕЛ ОПЕРАТОРОВ>

Секция описаний может появляться несколько раз в тексте программы, но использовать имена (идентификаторы) можно только после того, как они описаны. Существует несколько способов использовать данную возможность. Например, иметь файлы с отдельными модулями. Перед трансляцией эти файлы могут объединяться вместе с основной программой. Другими словами, обеспечиваются простейшие средства работы с библиотекой модулей Паскаля в исходном виде.

Пример:

  ФАЙЛ:
         (* ОПРЕДЕЛЕНИЕ ГРАФИЧЕСКОГО МОДУЛЯ *)
         VAR ... (* ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ФУНКЦИЙ *)
         PROCEDURE (* ОПИСАНИЕ ГРАФИЧЕСКИХ ФУНКЦИЙ *)
         PROCEDURE ...
         (* КОНЕЦ ГРАФИЧЕСКОГО МОДУЛЯ *)
  ФАЙЛ:
         (* ФАЙЛ ОСНОВНОЙ ПРОГРАММЫ *)
         VAR ... (* ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ *)
         BEGIN (* ТЕКСТ ПРОГРАММЫ *) END.

9.1. Использование Макроассемблера

Паскаль, реализованный для ДВК, даёт возможность включать в любое место программы отдельные фрагменты на языке Макроассемблер. Части программы, написанные на Макроассемблере, могут использовать переменные из программы на языке Паскаль, хотя для этого требуется некоторое понимание процесса организации выполнения. Для включения фрагмента на Ассемблере используется специальный вид комментариев, например:

         PROCEDURE EMTTRAP (N:INTEGER);
         BEGIN
           (*¤C                  ;НАЧАЛО ФРАГМЕНТА НА МАКРО
                 MOV N(SP),-(SP) ;ПАРАМЕТР "N" -> В СТЕК
                 EMT 53          ;ВЫЗВАТЬ ДИСПЕТЧЕР EMT
           *)
         END     (* EMTTRAP*)

При использовании Макроассемблера следует помнить, что основанием счисления числовых констант по умолчанию является 10, а не 8.

9.2. Внешние и фортрановские подпрограммы (процедуры)

Данный Паскаль допускает использование "внешних" процедур и функций, которые транслируются отдельно от основной программы. Это позволяет использовать библиотеки модулей. Объявление внешней процедуры осуществляется ключевым словом "EXTERNAL". Использование ключевого слова "FORTRAN" приведёт к вызову подпрограммы в соответствии с соглашениями исполняющей системы с языка ФОРТРАН/ФОДОС-2 следует отметить, что передача параметров в подпрограмму на языке ФОРТРАН осуществляется по ссылке, а не по значению, т.е. все параметры должны быть объявлены, как VAR (переменные).

Примеры:

         PROCEDURE ERASE; EXTERNAL
         FUNCTION DIFFERENCE(VAR X,Y:REAL):REAL; FORTRAN;