Подключите Ваш компьютер к проекту распределённых вычислений!
Этим Вы окажете большую помощь науке и медицине.
См. подробнее: http://solidstate.karelia.ru/~yura/pyldin/yura/computing.htm


<< Вернуться к содержанию





      НАУЧНО-ИССЛЕДОВАТЕЛЬСКАЯ И ПРОИЗВОДСТВЕННАЯ ЛАБОРАТОРИЯ
                       "ПРОГРАМНО ОСИГУРЯВАНЕ"
      -------------------------------------------------------









                     ПЕРСОНАЛЬНЫЙ МИКРОКОМПЬЮТЕР
                         ПЫЛДИН 601/601А


                             UniPASCAL

                            версия 1.00

                     РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ

                            редакция 2












                           София - 1989


         2                                                       UniPASCAL
         -----------------------------------------------------------------

         Copyright (с) 1989 НИПЛ"Програмно осигуряване", София, НРБ

              UniDOS и UniBIOS являются регистрированными торговыми марками
         и наименованиями НИПЛ"Програмно осигуряване".
              "Пылдин" является регистрированной торговой маркой и наимено-
         ванием Содружества "АБАКУС", НРБ.

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


         Программный дизаин и реализация: Георги Петров

         Редакция: к.т.н. инж. Недялко Тодоров

              НИПЛ "Програмно осигуряване"  благодарит каждого, кто вышлет
         свои замечания, рекомендации и деловые предложения по адресу:

                Болгария 1126 София,
                бульвар "Антон Иванов" 5
                НИПЛ"Програмно осигуряване"

         UniPASCAL                                                       3
         -----------------------------------------------------------------

                                С О Д Е Р Ж А Н И Е

         ЧАСТЬ 1 - ОПИСАНИЕ ЯЗЫКА

            1. Основные понятия языка программирования UniPascal         5
               1.1. Расширенные формы Бэкуса-Наура (РБНФ)                5
               1.2. Основные символы языка UniPascal                     6
               1.3. Идентификаторы                                       7
               1.4. Зарезервированные слова в UniPascal                  7
               1.5. Числовые константы                                   8
               1.6. Строки (символьные константы)                        9
               1.7. Комментарии (примечания)                            10

            2. Общая структура программы                                11
               2.1 Заголовок программы                                  11
               2.2. Тело процедуры, функции или программы (блок)        12
               2.3. Раздел описания меток                               12
               2.4. Раздел описания констант                            13
               2.5. Раздел описания типов                               13
               2.6. Раздел описания переменных                          14
               2.7. Раздел описания процедур и функций                  14
               2.8. Правила видимости и области действия имен и меток   15

            3. Типы данных                                              17
               3.1. Простые типы данных                                 17
                    3.1.1. Порядковые типы данных                       17
                           3.1.1.1. Перечисляемый тип                   17
                           3.1.1.2. Логический тип                      18
                           3.1.1.3. Целый тип                           19
                           3.1.1.4. Тип диапазона                       20
                           3.1.1.5. Символьный тип                      20
                    3.1.2. Вещественный тип данных                      21
               3.2. Структурированные типы данных                       21
                    3.2.1. Массивы и индексные переменные               22
                    3.2.2. Записи                                       23
                    3.2.3. Множества                                    25
                    3.2.4. Файлы                                        26
               3.3. Тип указатель                                       27
               3.4. Совместимость типов                                 28

            4. Переменные                                               29
               4.1. Описание переменных                                 29
               4.2. Обращение к переменной                              29

            5. Выражения                                                31
               5.1. Синтаксис                                           31
               5.2. Операции                                            32
                    5.2.1. Арифметические операции                      32
                    5.2.2. Логические операции                          33
                    5.2.3. Операции над множествами                     33
                    5.2.4. Операции отношения                           34

         4                                                       UniPASCAL
         -----------------------------------------------------------------


            6. Операторы                                                35
               6.1. Простые операторы                                   35
                    6.1.1. Пустой оператор                              35
                    6.1.2. Оператор присваивания                        35
                    6.1.3. Оператор процедуры.                          36
                    6.1.4. Оператор перехода.                           36
               6.2. Сложные операторы                                   36
                    6.2.1. Последовательность операторов                37
                    6.2.2. Составный оператор                           37
                    6.2.3. Условные и выбирающие операторы              37
                    6.2.4. Операторы цикла                              38
                    6.2.5. Операторы присваивания                       40

            7. Процедуры и функции                                      43
               7.1. Описание процедур                                   43
               7.2. Описание функций                                    44
               7.3. Параметры                                           45
                    7.3.1. Списки формальных параметров                 46
                    7.3.2. Фактические параметры                        48

            8. Модули                                                   49
               8.1. Раздел описаний                                     50
               8.2. Раздел реализации                                   51
               8.3. Особенности                                         51
               8.4. Пример использования модулей                        52


         ЧАСТЬ 2 - ОПИСАНИЕ КОМПИЛЯТОРА

            9. Компилятор UniPASCAL                                     53
               9.1. Вызов компилятора                                   53
               9.2. Стандартные расширения имен файлов                  53
               9.3. Внутренное представление данных                     54

           10. Управление компиляцией                                   55
              10.1. Переключающие директивы                             56
              10.2. Директивы с параметром                              58
              10.3. Условная компиляция                                 58
                    10.3.1. Директивы DEFINE и UNDEF                    58
                    10.3.2. Директивы IFDEF, IFNDEF, IFOPT,
                            ELSE, ENDIF                                 59

           11. Диагностические сообщения компилятора                    60
               11.1. Ошибки, не влияющие на процесс компиляции          60
               11.2. Нефатальные ошибки                                 61
               11.3. Фатальные ошибки                                   70

           12. Диагностические сообщения интерпретатора                 72

            Приложение 1 - Формальное описание языка                    73

            Приложение 2 - Стандартные процедуры и функции              80

         UniPASCAL - Основные понятия                                    5
         -----------------------------------------------------------------




              1.  ОСНОВНЫЕ ПОНЯТИЯ ЯЗЫКА ПРОГРАММИРОВАНИЯ UniPascal

              1.1.  Расширенные формы Бэкуса-Наура (РБНФ)

              Для описания синтаксиса языков высокого уровня применяются
         так называемые формы Бзкуса-Наура (БНФ).

              Ниже дано описание модифицированного варианта этих форм,
         называемого "расширенные формы Бэкуса-Наура" (РБНФ).

              Описание синтаксиса языка програмирования с помощью РБНФ
         состоит из набора правил, еще называемых "продукциями".  Множество
         таких правил называется "грамматикой".  Каждое правило состоит из
         нетерминального символа и РБНФ-выражения, разделенных знаком
         равенства.  Правило завершается точкой.  Нетерминальный символ
         представляет собой "метаимя", которое определяется
         РБНФ-выражением.

              РБНФ-выражение может быть пустым или содержать множество
         терминальных символов, нетерминальные символы и следующие
         метасимволы:

              Метасимвол       Значение
         --------------------------------------------------------------
                  =            Равно по определению
                  |            Или (альтернатива)
                  .            Конец правила
                 {A}           0 или более вхождений A в правило
                 [A]           0 или 1 вхождение A в правило
                (A|B)          Группирование: или A, или B
           "ABC" или 'ABC'     Терминальный символ ABC
               метаимя         Нетерминальный символ с именем "метаимя".

              Метасимвол = служит для разделения правой от левой части
         синтаксического правила (для БНФ это ::= ).  Альтернативы
         разделяются метасимволом | (как в БНФ).

              Обозначения терминальных и нетерминальных символов в РБНФ
         сильно отличаются от соответствующих обозначений в БНФ.  В РБНФ
         нетерминальные символы представляют собой набор из букв, цифр и
         символа подчеркивания '_', а в БНФ нетерминалы заключены в скобках
         < >.  Терминальные символы в РБНФ заключаются в " или '.
              В конце каждого правила ставится точка (.).
              Запись {A} означает повторение символа А произвольное число
         раз (включая ноль раз), т.е.  {А} - сокращенная запись NULL
         |A|AA|AAA|..., где NULL - пустая цепочка.
              Запись [A] означает повторение символа А нуль или один раз.
         [A] - это сокращенная запись на NULL |A.
              Изпользование круглых скобок - традиционное для
         математических выражений и показано на примере:  вместо выражения
         S = А X В | А Y В  можно записать :  S = A ( X | Y ) B.

         6                                    UniPASCAL - Основные понятия
         -----------------------------------------------------------------

              В качестве примера использования РБНФ опишем ими их
         собственный синтаксис:

         Syntax      =  {Production}

         Production  =  NonTerminal '=' Expression '.'.

         Expression  =  Term { '|' Term }.

         Term        =  { Factor }.

         Factor      =  NonTerminal |
                        Terminal |
                        '(' Expression ')' |
                        '[' Expression ']' |
                        '{' Expression '}' .

         Terminal    =  "'" Character "'" |
                        '"' Character '"' .

         NonTerminal =  Letter { Letter | Digit | '_'}.

         Letter      =  'A' | 'B' | ... | 'Z' | 'a' | 'b' | ... | 'z'.

         Digit       =  '0' | '1' | ... | '9'.

         Character   =  Letter | Digit | '!' | '@' | '#' | ... .


              Многоточием обозначен пропуск символов в тексте описания.



              1.2.  Основные символы языка UniPascal

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

              Используеться следующее подмножество символьного набора ASCII.
         - Прописные и строчные буквы латинского алфавита
           /A,B,C,...Z,a,b,c,...z/

         - Цифрры с 0 до 9 (0,1,2,3,4,5,6,7,8,9)

         - Специальные символы:
           пробел, " # $ & ' ( ) * + , - . / : ; < = > [ ] ^ _ { | }

         - Пары специальных символов: (отделенные запятой)
           <=,       >=,  <>,  :=,  .., (*, *).

              Программа на Паскале состоит из лексем и символов -
         разделителей.  Лексемы строятся из перечисленных выше символов и
         разделяются на 5 групп:  специальные символы, идентификаторы,
         зарезервированные слова, числовые константы и строки.
         Разделителями между лексемами являются:  пробел, комментарий,
         специальные символы и конец строки.  Строка программ не должна
         превышать 127 символов.

         UniPASCAL - Основные понятия                                    7
         -----------------------------------------------------------------

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

              Правила РБНФ для букв и цифр:

         Letter =   'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' |
                    'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' |
                    'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' |
                    'Y' | 'Z' |
                    'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' |
                    'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' |
                    'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' |
                    'y' | 'z' .

         Digit =    '0' | '1' | '2' | '3' | '4' |
                    '5' | '6' | '7' | '8' | '9'.


              1.3.  Идентификаторы

              Идентификаторы (Identifiers) служат для обозначения констант,
         меток, типов, переменных, полей записи, процедур, функций, модулей
         и программ.
                      Ident = Letter { Letter | Digit | '_' }.
              Идентификатор - это комбинация произвольного количество букв
         и цифр, начинающаяся буквой.  Допустимы только буквы латинского
         алфавита.
              Существуют следующие исключения для приведенного выше
         правила:
              - запрещается использовать в качестве идентификаторов
         зарезервированные слова;
              - идентефикаторы, отличающиеся только использованием
         прописных или строчных букв, считаются эквивалентными.
         Например:        UniPascal = unipascal;
              - на общую длину идентификаторов не накладываются никаких
         ограничений, но считается, что значимы только первые 8 символов.
         Идентификаторы, не отличающиеся первыми восмью символами считаются
         одинаковыми.
         Например:        LongIdent = LongIdentifier;
              - использованный в идентификаторе символ подчеркивания "_"
         игнорируется.  Это означает, что идентификаторы UniPascal и
         Uni_Pascal - одинаковы.


              1.4.  Зарезервированные слова в UniPascal
              Зарезервированными в UniPascal-е являются следующие слова:
         and        array        begin          case      const
         div        do           downto         else      end
         file       for          function       goto      if
         in         interface    implementation label     mod
         nil        not          of             or        packed
         procedure  program      record         repeat    set
         segment    then         to             type      until
         unit       uses         var            while     with
         xor

         8                                    UniPASCAL - Основные понятия
         -----------------------------------------------------------------


              При записи зарезервированных слов можно использовать прописные
         и строчные буквы или комбинации из них.
              Например:  Begin, BEGIN, begin, begiN

              Использование символа подчеркивания в зарезервированных
         словах не разрешается, т.е.  down_to - идентификатор, а не
         зарезервированное слово.


              1.5.  Числовые константы
              При записи целых и вещественных констант в UniPascal-е
         используется обычная запись в десятичной системе счисления, при
         этом для вещественных чисел используется десятичная точка.

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

              Букву "E" в вещественных константах следует интерпретировать
         как "умножить на 10 в степени".

              Целые константы должны быть в интервале [-2147483648,
         2147483647], или, если они шестнадцатиричные, в интервале [$0,
         $FFFFFFFF].


         HexDigit =  Digit | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' |
                             'a' | 'b' | 'c' | 'd' | 'e' | 'f'.

         Decimal =   Digit { Digit | '_'}.

         IntConst =  Decimal | '$' HexDigit { HexDigit | '_'}.

         RealConst = Decimal '.' Decimal [ 'E' ['+' | '-'] Decimal ].

         Примеры:
         Целые константы :   0, 1, 259, $0, $f, $7fff, $EF5
         Вещественные константы: 0.0, 1.0, 259.0, 0.0005, 1.0E-23.

              В отличии от стандартного Паскаля, допускается группировать
         цифры одного числа знаком подчеркивания '_'.  Это предусмотрено
         для удобного чтения длинных чисел.  Например, для компилятора
         числа 1000000000 и 1_000_000_000 эквивалентны, но для человека
         гораздо легче воспринять вторую запись.

         Примеры:
                 1)   1.0_E_-10           =       1.0E-10
                 2)   $FFFF_FFFF          =       $FFFFFFFF

         UniPASCAL - Основные понятия                                    9
         -----------------------------------------------------------------


              1.6.  Строки (символьные константы )

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

         Примеры:    ' пример '
                     " пример "
                     ' ошибка "

              Если необходимо записать кавычки внутри строки, то нужно
         повторить их дважды.
         Пример:     'Эта строка содержит апостроф: ''.'.
         Другая запись то-же строки:  "Эта строка содержит апостроф: '.".

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

              Есть особый вид строки - односимвольная, которая состоит
         только из одного символа.  Ее можно записать и так:
                           #n, где n - ASCII код символа.

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

              В строке могут быть записаны все символы набора ASCII и все
         буквы кириллицы.

         CharConst   = '"' ASCII_8 '"' |
                       "'" ASCII_8 "'" |
                       '#' IntConst.

         StringConst = { '"' { ASCII_8 } '"' |
                         "'" { ASCII_8 } "'" |
                         '#' IntConst          } |
                       "''" |
                       '""' .

              Здесь ASCII_8 означает символ 8-битового ASCII набора,
         включающий и буквы кириллицы, а IntConst - это ASCII код символа
         (целое число без знака в интервале [0..255]).

         Примеры: 1) 'Это строка'
                  2) 'Эта строка содержит '''
                  3) "Эта строка содержит ' "
                  4) 'Эта строка содержит " '
                  5) "Эта"
                           'длинная '
                                    "строка"

         10                                   UniPASCAL - Основные понятия
         -----------------------------------------------------------------



              1.7.  Комментарии

              Комментарии предназначены для записи пояснений в тексте
         программы и при трансляции игнорируются.

              Правила использования комментария следующие:
              1) Если комментарий заключен в фигурных скобках { }, то в ним
         нельзя использовать правую фигурную скобку }.  Например:  { Это }
         неправильный комментарий }.
              2) Если комментарий заключен в (* *), то в нем нельзя
         использовать комбинацию *).  Например:  (* И это *) неправильный
         комментарий *).
              3) Нельзя ставить разные ограничители с двух сторон, т.е
         невозможно начинать коментарий с { и закончивать с *) и наоборот.
              4) Не должно быть вложенных комментарий одного и того же
         типа.  Например:  { Неправильный { комментарий }!  }
              5) Если комментарий начинается символом $, то это
         специальный комментарий и он предназначен для управления работой
         компилятора.  Например:  (*$I+*).
              6) Компилятор разрешает написать текст программы в несколь-
         ких файлах (см. управление режима компиляции), но один комментарий
         должен быть записан полностью в одном файле.

         Comment =       '{' { ASCII_8 }   '}' |
                         '(*'{ ASCII_8 }   '*)'.

              Примеры правильных комментариев:
         { Символы *) допустимы, потому что комментарий начинается с {.  }
                      (*  Символы * и ) не последовательны. *)

         UniPASCAL - Общая структура программы                          11
         -----------------------------------------------------------------





              2.  ОБЩАЯ СТРУКТУРА ПРОГРАММЫ

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

              В UniPascal-е кроме этих двух частей (Program_Heading, Block)
         разрешается написать и описание (Uses_Clause), которое указывает
         какие модулы будут использованы в этой программе.

              Формальное описание синтаксиса программы на UniPASCAL-е:

         Program =       Program_Heading
                           Uses_Clause
                         Block "."      .
         UsesClause =    { 'uses' Ident_List ';' }.
         IdentList =     Ident { ',' Ident }.

         Где: Ident - имя модуля(ей), включаемого в программу.



              2.1 Заголовок программы

              В заголовке программы указывается имя программы и имена
         стандартных файлов.  Стандартные внешние файлы следующие:

         - Input     - стандартный файл ввода (обычно клавиатура);
         - Output    - стандартный файл вывода (обычно зкран);
         - Message   - стандартный файл ввода/вывода
                       (клавиатура и экран);
         - Aux       - стандартный файл ввода/вывода (в зависимости от
                       UniDOS)
         - Printer   - стандартный файл вывода (обычно печатающее
                       устройство)

              Синтаксис заголовка:

         Program_Heading= 'program' Ident ['('External_Files')' ] ';'.
         External_Files = Ident { ',' Ident }.

         Где: Ident - имя внешнего файла.

         12                          UniPASCAL - Общая структура программы
         -----------------------------------------------------------------


              2.2.  Тело процедуры, функции или программы (блок)

              Блок - это основная конструкция построения программ, процедур
         и функций.  Блок содержит раздел описаний (Declarations) и раздел
         операторов.  В разделе описаний описываются все объекты, которые
         используются программой.  Они могут быть:  метки (Label), констан-
         ты (Const), типы (type), переменные (var), процедуры (procedure)
         или функции (function).  В отличии от стандартного Паскаля здесь
         порядок описаний не имеет значения.  Только описание объекта дол-
         жно предшествовать его использованию в блоке.  Раздел описаний
         может быть и пустой.  В разделе операторов описываются действия
         над объектами, уже определенными в разделе описаний.

              Синтаксис блока:

         Block =         [Declarations]
                         'begin'
                         Statement { ';'
                         Statement }
                         'end'.

         Declarations =  { LabelDecl |
                           ConstDecl |
                           TypeDecl |
                           VarDecl |
                           PFDecl }    .

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


              2.3.  Раздел описания меток

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

              Синтаксис описания метки:

         Label =         (Ident | IntConst).

         LabelDecl =     'label' Label { ',' Label } ';'.

              Сама метка представляет собой целое число (от 0 до 9999) или
         идентификатор.  Если для метки используется целое число, то первые
         незначащие нули игнорируются, т.е.  метки 0077 и 77 считаются оди-
         наковыми.

              Пример описания меток:  Label 11, Stop, Continue, 0;

         UniPASCAL - Общая структура программы                          13
         -----------------------------------------------------------------


              2.4.  Раздел описания констант

              В разделе описания констант описываются идентификаторы, кото-
         рые используются в качестве имен констант.

              Синтаксис раздела описания констант:

         ConstDecl =     'const' Ident '=' Constant ';'
                               { Ident '=' Constant ';' }.

         Constant =      IntConst |
                         RealConst |
                         StringConst |
                         CharConst |
                         ConstExpression.

         ConstExpression= Expression.

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

         Пример: const N   = 100;
                       N_2 = N * N;
                       Pi  = 3.141596;
                       Name= 'UniPascal';


              2.5.  Раздел описания типов

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

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

              Синтаксис раздела определения типов:
         TypeDecl =      'type' Ident '=' Type ';'
                              { Ident '=' Type ';' }.

         14                          UniPASCAL - Общая структура программы
         -----------------------------------------------------------------


         Type =          (SimpleType |
                          PointerType |
                          StructuredType |
                          StringType).

         SimpleType =    Ident | OrdinalType | RealType.

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


              2.6.  Раздел описания переменных


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

              Синтаксис переменных:

         VarDecl =       'var' IdentList ':' Type ';'
                             { IdentList ':' Type ';' }.
         IdentList =     Ident { ',' Ident }.

         Где:  Ident - идентификатор (имя описываемой переменной).

              Описание переменной задает связь между идентификатором и
         определенным типом данных.




              2.7.  Раздел описания процедур и функций

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

              Синтаксис:

         PFDecl =        { ProcDecl }|{ FuncDecl }.

         UniPASCAL - Общая структура программы                          15
         -----------------------------------------------------------------


              2.8.  Правила доступности и области действия имен и меток

              Идентификаторы и метки являются локальными в рамках блока, в
         начале которого они описаны.  Это означает, что вне этого блока
         они недoступны.  Идентификаторы доступны везде в этоm блокe,
         включая вложенные блоки.  Идентификаторы и метки, описанные в
         блоке, представляющей собой программой, называются глобальными.
         Глобальные идентификаторы доступны везде в программе.

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

              Ниже приведен пример очень трудно обнаруживаемой ошибки.

         var Man: Person;
         type Person = record
                ...
              end; { Person }

              Если во внешним блоке есть декларация типа Person, то
         переменная Man будет из "старого" типа, а не из типа, который
         описывается в рамках текущего блока.

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

              Например:
         type PersonPtr = ^Person;
              Person = record
                ...
              end; { Person }

         16                          UniPASCAL - Общая структура программы
         -----------------------------------------------------------------


              Здесь PersonPtr является указателем на Person, несмотря на
         то, есть ли во внешнем блоке другое описание этого идентификатора.
         Но положение весьма различное, когда имеем следующие описания:

         type PersonPtr= ^Person;
         type Person = ...

              В этом случае PersonPtr или является указателем на тип,
         описаный в предыдущем блоке (если есть такое описание), или
         выдается сообщение об ошибке.

              Можно переописать и стандартные типы.
              Например:

         type
            WorkType = integer;  { integer - стандартный тип
                                   integer }
            integer  = real;     { real - стандартныя тип
                                   real }
            real     = WorkType; { real описывается как
                                   integer }

              После этих дефиниций, если описать переменную r так:

         var
            r        : real;

         то ей можно присваивать только целые значения.  Если в тексте
         программы встретится

         r:= 1.5;

         то выдается сообщение об ошибке.

              Пример демонстрирует возможность переопределения только
         стандартных идентификаторов.

         UniPASCAL - Типы данных                                        17
         -----------------------------------------------------------------




              3.  ТИПЫ ДАННЫХ


              3.1.  Простые типы данных

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


              3.1.1.  Порядковые (ORDINAL) типы данных

              3.1.1.1.  Перечисляемый тип

              Перечисляемый тип (ENUMERATED) определяется перечислением
         всех возможных значений.  Описание состоит из списка констант.
         Описание синтаксиса следующее:

         Enumerated = '(' IdentList ')'.

              Пример (приведенные определения валидны до конца
         параграфа, чтобы не писать их перед каждым примером):
         type
            Color = (Black, Red, Green, Orange, Red, White);
            DayOfWeek = (Monday, Tuesday, Wednesday,
                         Thursday, Friday, Saturday, Sunday);
         var CarColor: Color;
             yesterday, today, tomorrow: DayOfWeek;

              Для любого перечисляемого типа можно записать:  T = (W_0,
         W_1, ..., W_n); где T - идентификатор типа, а W0, W1, ...  Wn -
         константные идентификаторы. В силе следующие отношения и правила:
              1) W_i <> W_j, если i <> j (различимость)
              2) W_i < W_j, если i < j (упорядоченность)
              3) Значениями типа T могут быть только W_0, W_1, ..., W_n
              4) Существует взимно-однозначное соответствие между
         значениями типа и положительными целыми числами в интервале [0,n].

              Рассмотрим операции, применяемые для перечисляемого типа:
              - Присваивание значения.  Переменной типа T можно присваивать
         новое значение.
         Например:
              CarColor:= Red; today:= Tuesday;

              - Отношение.  Операции отношения <, >, <=, >=, =, <>,
         определены для любых двух обектов из одного и того же
         перечисляемого типа.
         Например:
              if today <> Sunday then ...;

         18                                        UniPASCAL - Типы данных
         -----------------------------------------------------------------


              - Получение порядкового номера. Осуществляет стандартная
         функция ORD, котороя определена для любого перечисляемого типа и
         как результат дает неотрицательное число.
         Например:
              ORD(Monday) = 0

              - Получение значения перечисляемого типа по заданному
         порядковому номеру.  Любой перечисляемый тип определяет функцию
         над целыми неотрицательными числами в перечисляемом типе с тем-же
         самым именем.  Любое число может получить значения перечисляемого
         типа.
         Например:
              Color(1) = Red, DayOfWeek(6) = Synday.

              - Получение минимального и максимального значения.
         Определены стандартные функции MIN, MAX над каждым перечисляемым
         типом, которые, соответственно, дают минимальное и максимальное
         значение зтого типа.
         Например:
              Min(Color) = Black, Max(DayOfWeek) = Sunday.

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

                  Succ(W_i) = W_(i+1), для i = 0, 1, ..., n-1
                  Pred(W_i) = W_(i-1), для i = 1, 2, ..., n

         Например: Succ(Friday) = Saturday, Pred(Thursday) = Wednesday.

              В случаях, когда порядковый номер полученного результата
         выходит из интервала [0, n], операции над обьектами являются
         неопределенными и приводят к ошибке.

         Примеры неправильного применения функций:
              Succ(Max(Color)), Pred(Min(DayOfWeek)), DayOfWeek(9).



              3.1.1.2.  Логический тип

              Логический тип может быть формально описан так:

              type Boolean = (False, True);

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

              - Отрицание (не).  NOT
              - Коньюнкция (и).   AND или &
              - Дизьюнкция (или). OR  или |
              - Исключающее или.  XOR  (сумма по модулю 2)

         UniPASCAL - Типы данных                                        19
         -----------------------------------------------------------------

              Необходимо обратить внимание на то, что объект логического
         типа - это не только переменная или константа типа Boolean, но и
         любое выражение типа Boolean.  Резултат выполнения этих операций
         тоже логического типа.
         Например:
              55 < 77 = true, (false > true) = false

              В Pascal-е принят следующий приоритет операций:

         Самый высокий: NOT и функции
                        *, /, div, mod, and, &
                        +, -, OR, |, XOR
         Самый низкий:  =, <>, <, <=, >, >=, in

              Операции одинакового приоритета выпольняются слева направо.
         Если не использованы скобки, то операции выполняются в порядке
         убывания их приоритетов.
         Например:
            not P and Q         = (not P) and Q
            P <= Q and R     = P <= (Q and R)
            A = B and C <= D = (A = (B and C)) <= D

              Последный пример обычно считается ошибкой так, как имеется в
         виду совсем другое:  (A = B) and (C <= D).

              В Pascal-е нельзя записывать двухсторонное неравенство.
         Например, вместо 0 < X < 22 следует записать (0 < X) and (X < 22).

              В UniPascal-е вычисление логического выражения прекращается
         сразу после получения результата.  Например, если нужно вычислить
         выражение P AND Q и значение P = false, то Q не будет вычислятся,
         потому что значение выражения уже известно - Fаlse.



              3.1.1.3.  Целый тип

              В UniPascal-е есть несколько разных целых типов,
         представляющих целые числа в разных диапазонах.  Все они
         совместимы в интервале их пересечения.

                Тип            Представленние числа в интервала
              -------------------------------------------------
              Integer                   -32767..32767
              ShortInt                    -128..127
              Cardinal                       0..65535
              Natural                        0..32767
              ShortCard                      0..255
              LongInt              -2147483647..2147483647

              Над обьектами целого типа определены следующие операции:
         сложение (+), вычитание (-), умножение (*), деление (div),
         получение остатка деления остатка (mod) и смена знака (одноместная
         операция минуса) (-).  Если два операнда имеют разные типы до
         операции, то они приводятся к минимальном типу, включающему
         диапазоны обоих типов.

         20                                        UniPASCAL - Типы данных
         -----------------------------------------------------------------

              Примеры:
         1)   Результат операции над операндами типа ShortInt и Natural
         будет типа Integer, если операнд типа ShortInt отрицательный.
         Иначе результат будет типа Natural.
         2)   Результат зависит и от типа переменной, которой он
         присваивается.  Если получим результат в диапазоне [32767, 65535]
         и присвоим его переменной типа Integer, то значение переменной
         будет отрицательным.
         3)   При арифметических операциях целого типа не производится
         проверка на переполнение, т.е.  если к переменной типа Cardinal с
         значением 65535 добавите 1, то получите 0, а не ошибку при
         выполнении программы.

              Следующие стандартные функции определены над целочисленными
         типами и дают целочисленный результат:
              - ABS(x) абсолютная величина аргумента;
              - SQR(x) аргумент в степени 2  (x * x);
              - Все стандартные процедуры и функции перечисляемого
          типа можно использовать и для типов целых чисел.



              3.1.1.4.  Тип диапазона

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

              SubRange = Constant '..' Constant.
              Пример:
         type
            WorkDays = Monday..Friday;  (* предполагаем, что уже *)
            WeekEnd  = Saturday..Sunday;(* описан тип DayOfWeek  *)
            ByteType = 0..255;



              3.1.1.5.  Символьный тип

              Значения, которые могут принимать объекты символьного типа
         (CHAR) - это все символы 8-битового ASCII набора.  К ним добавлена
         кириллица.  Для 8-битового ASCII набора следующие
         подмножества упорядочены и связаны (условие удовлетворяется
         стандартом MIK):
              1) Арабские цифры                        (от 0 до 9)
              2) Прописные буквы латинского альфавита  (от A до Z)
              3) Строчные буквы латинского альфавита   (от a до z)
              4) Прописные буквы кириллицы             (от А до Я)
              5) Строчные буквы  кириллицы             (от а до я)

              Все стандартные процедуры и функции для описанных выше типов,
         кроме вещественного, применимы и для символьного типа.  Кроме них
         в Pascal-е определена стандартная функция CHR с аргументом целого
         типа, в результате выполнения которой выдается буква, порядковый
         номер которой равен аргументу функции.

         UniPASCAL - Типы данных                                        21
         -----------------------------------------------------------------


              3.1.2.  Вещественный тип данных

              Вещественный тип (Real) в UniPascal-е включает вещественные
         числа.  Точность вычислении - 7 цифр.  Это означает что только
         первые 7 значащых цифр любого вещественного числа определяют ве-
         личину мантиссы.  Порядок вещественных чисел в диапазоне [-38,38].

              Для вещественных чисел определены следующие операции:
         сложение (+), вычитание (-), умножение (*), деление(/),
         унарная операция (-).
              Если при операции деления (/) оба операнда целого типа,
         они приводятся перед выполнением к вещественному типу.
              Следующие стандартные функции определены над вещественным
         типом и результат всегда вещественного типа:
              - ABS(x) абсолютная величина аргумента  (x: Real);
              - SQR(x) аргумент в степени 2 (x * x)   (x: Real);

              Следующие функции могут иметь параметр как вещественного так
         и целого типа, но результат всегда вещественного типа.
              - SIN(X), COS(X), аргумент функции задан в радианах;
              - Ln(X)           натуральный логарифм
              - Exp(X)          экспоненциальная функция
              - SQRT(X)         квадратный корень  аргумента

              Следующие функции имеют вещественный параметр, но результат
         всегда целого типа:
              - Trunc(X) - целое число, не превышающее X (отрезание);
              - Round(X) - целое число, не меньше X (округление).

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



              3.2.  Структурированные типы данных

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

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

              Синтаксис:

         StructuredType= ['packed'] (ArrayType |
                                     RecordType |
                                     SetType |
                                     FileType).

         22                                        UniPASCAL - Типы данных
         -----------------------------------------------------------------

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


              3.2.1.  Массивы и индексные переменные

              Синтаксис описания:

          ArrayType = 'array' '['IndexType{','IndexType}']' 'of' Type.
          IndexType = SubRange | Enumerated | Char | Boolean.

              Любой объект типа массива (ArrayType) состит из фиксированно-
         го числа компонент.  Все компоненты относятся к одному типу, назы-
         ваемому типом компонент (Type).  Число компонент определяется при
         описании этого типа.  Каждая компонента может быть явно обозначена
         с помощью имени переменной-массива, за которым в квадратных скоб-
         ках следует индекс.  Индекс специфицирует компоненту массива.  Его
         тип называется тип индекса (IndexType).  Индексы можно вычислять.

         Пример:
             Если даны дефиниции:
         const
            AreaLimit = 100;
         type
            AreaIndex = 0..AreaLimit;
            AreaType  = array[AreaIndex] of integer;
         var
            I         : AreaIndex;
            Area      : AreaType;

         то Area[I] обозначает I-тую компоненту массива Area.

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

              Например:
         var
            A: array [LoInd1..HiInd1] of
               array [LoInd2..HiInd2] of Type;

              В этом случае через A[I][J] обозначаем J-тую компоненту (типа
         Type) I-той компоненты массива A.  Синтаксис языка позволяет запи-
         сать этот пример более сокращенно:
         var
            A: array [LoInd1..HiInd1, LoInd2..HiInd2] of Type;

              Компоненты массива можно обозначать и через A[I, J].

         UniPASCAL - Типы данных                                        23
         -----------------------------------------------------------------

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

              Компонентам массива можно присваивать значения того же типа.
         Если имеем две переменные одного типа массива, то можно одной при-
         своить значение другой.  Например, если имеем дефиницию:
         var A, B:  AreaType;
         то возможно присваивание  A:= B;
         и оно означает: "Для всех I из диапазона IndexType: A[I]:= B[I]"

              Над объектами типа массива определены и отношения "равно" (=)
         и различно (<>).  Они применяются для всех компонент объектов и
         возвращают результат типа Boolean.

              При работе с упакованными массивами с компонентами типа Char
         существуют следующие дополнительные возможности.  Можно применять
         все операции сравнения:  =, <>, <, <=, >, >=.        Упорядоченность на-
         чинается с первой компоненты массива и определяется порядком, су-
         ществующим для типа Char.  Специфичным символьным массивом являет-
         ся тип string (строка, символьная строка).  Его длина динамична.
         Она изменяется от 0 до некоторого максимального значения, опреде-
         ленного при описании типа и не превышающего 255.
              Синтаксис:

         StringType = 'string' '[' Constant ']'.

         где Constant в диапазоне [1..255].



              3.2.2.  Записи

              Синтаксис описания:

         RecordType =    'record' FieldList 'end'.

         FieldList =     FixedPart [';'] |
                         VariantPart [';'] |
                         FixedPart ';' VariantPart [';'].

         FixedPart =     FieldIdent { ',' FieldIdent } ':' Type {';'
                         FieldIdent { ',' FieldIdent } ':' Type }.

         VariantPart =   'case' TagField 'of'
                            ConstList ':' '(' FieldList ')' {';'
                            ConstList ':' '(' FieldList ')'}.

         TagField =      [TagIdent ':'] TagFieldType.
         TagFieldType =  OrdinalType.
         OrdinalType =   IntType |
                         Enumerated |
                         Subrange |
                         'Boolean' |
                         'Char'          .

         24                                        UniPASCAL - Типы данных
         -----------------------------------------------------------------

         IntType =       Integer |
                         ShortInt |
                         Cardinal |
                         Natural |
                         ShortCard       .

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

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

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

              Вариантная часть записи состоит из селектора варианта (Tag-
         Field) и одного или более вариантов.  Структура и значения каждого
         варианта задаются его списком полей.  Варианты специфицируются се-
         лектором варианта (TagField).  Здесь TagFieldType - тип, значения
         которого определяют варианты, а TagIdent - имя поля признака, в
         котором записывается значение, соответствующее определенному вари-
         анту.  TagFieldType может быть имя ординального типа (OrdinalType).

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

              Если существует поле признака, то активным будет вариант,
         которому предшествует константа, равная значению поля признака.

              Над объектами типа записи определены операции сравнения:
         равно (=) и различно (<>).

         UniPASCAL - Типы данных                                        25
         -----------------------------------------------------------------

              Например:
         type
            BookType = record
                         Name: string[31];
                         case AuthorKnown: boolean of
                           true:  (Author: string[33]);
                           false: ();
                       end;
         var
            Book: BookType;

              Теперь можно написать:
         Book.Name = 'Pascal User Manual and Report';
         Book.AuthorKnown:= TRUE;
         Book.Author:= 'K. Jensen, N. Wirth';
              (* ... текст программы ...  *)
         write(Book.Name, ' written by ');
         if Book.AuthorKnown
            then writeln(Book.Author)
            else writeln('Unknown author.');

              ПРИМЕЧАНИЯ:
              - Все имена полей должны быть уникальными, даже если они
         встречаются в разных вариантах;
              - Любой список полей может иметь только одну вариантную
         часть, которая должна следовать за фиксированной частью записи;
              - Каждый вариант может содержать в себе вариантную часть,
         т.е.  допускаются вложенные варианты;
              - Область действия идентификаторов перечисляемого типа,
         вводимых в типе записи, расширяется на вложенные блоки.


              3.2.3.  Множества

              Синтаксис описания:

        SetType =       'set' 'of' OrdinalType.

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

              В UniPascal-е число элементов не должно превышать 256 с
         порядковыми номерами в диапазоне от 0 до 255.

              Над объектами множественного типа можно применять следующие
         операции:
              =      равенство множеств
              <>     неравенство (различие) множеств
              <=, >= включение одного множества в другое
              +      объединение множеств
              *      пересечение множеств
              -      разность множеств

         26                                        UniPASCAL - Типы данных
         -----------------------------------------------------------------

              in     принадлежность значения из базового типа к множеству.
                     Левый операнд должен быть базового типа, а правый -
                     множественного типа. Операция возвращает результат
                     TRUE, если первый операнд является элементом второго и
                     FALSE - если не является.

              В UniPascal-е над объектами множественного типа определены и
         следующие стандартные процедуры:  Incl(s, x) и Excl(s, x), где па-
         раметр s является множеством, а параметр x - элементом базового
         типа множества.

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

              Синтаксис:

         Set =   '[' { SetItem {, SetItem } } ']'

              Здесь SetItem является описанием элемента множества.  SetItem
         может быть выражение, значение которого элемент или диапазон базо-
         вого типа.  Конструктор множества [] обозначает пустое множество
         для любого множественного типа.




              3.2.4.  Файлы

              Синтаксис описания:

         FileType =      'file' ['of' Type];

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

              Файл - это структура последовательного доступа, т.е.  в любой
         момент времени доступна только одна компонента файла.  Другие ком-
         поненты доступны при последовательном продвижении по файлу.  Число
         компонент (длина файла) не фиксируется при определении файла. Файл,
         не содержащий ни одной компоненты, называется пустым.

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

              Если слово "of" и описание типа (Type) пропущенны в описании
         типа файл, тогда он называется файлом неопределенного типа и ис-
         пользуется для осуществления прямого доступа к внешнему файлу. Его
         компоненты обрабатываются специальными процедурами.

         UniPASCAL - Типы данных                                        27
         -----------------------------------------------------------------

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

         type
            TEXT = file of char;

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

              - для обработки файлов определенного типа:  EoF, Read, Write,
         Reset, Open, Rewrite, Close.
              - допольнительние процедуры для обработки текстовых файлов:
         EoLn, ReadLn, WriteLn.
              - для обработки файлов неопределенного типа:  EoF, BlockRead,
         BlockWrite, Reset, Open, Rewrite, Close.



              3.3.  Тип указатель

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

              Синтаксис описания:
         PointerType =   '^' BaseType .
         BaseType =      TypeIdent .

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

              Над указателями определены только операции проверки на равен-
         ство и различие.  Значение NIL (пустой указатель) принадлежит всем
         типам указателей.  Оно не указывает ни на какой элемент.

              Для обработки объектов типа указатель используются следующие
         стандартные процедуры:
              New - создает динамическую переменную базового типа, резер-
         вируя часть оперативной памяти.
              Dispose - Освобождает резервированную для некоторой динами-
         ческой переменной память.
              Mark - Отмечает память некоторой динамической переменной для
         последующего освобождения.
              Release - Освобождает динамическую память, отмеченную проце-
         дурой Mark.

         28                                        UniPASCAL - Типы данных
         -----------------------------------------------------------------

              3.4.  Совместимость типов

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

              Значения объектов двух типов Т1 и Т2 можно присваивать один
         другому, если:
              - не файловые;
              - не структурированные типы с компонентами неприсваиваемого
         типа;
              - справедливо любое из четырех следующих условий:
                -- Т1 и Т2 представляют собой один и тот же тип;
                -- Т1 - real, а Т2 - integer;
                -- Т1 и Т2 - совместимые ординальные или множественные типы;
                -- Т1 и Т2 - совместимые строковые типы.

         UniPASCAL - Переменные                                         29
         -----------------------------------------------------------------



              4.  ПЕРЕМЕННЫЕ

              Переменная обладает типом, определяемым ее описанием и может
         принимать значения только этого типа.  Любая статическая перемен-
         ная, описанная в некотором блоке, порождается при активации блока
         и уничтожается по окончании активации.  Динамические переменные
         порождаются или уничтожаются при помощи процедур New и Dispose.




              4.1.  Описание переменных

              Переменные описываются в разделах описания переменных.  Опи-
         сание переменных вводит одно или более имен переменных и тип, к
         которому относится каждая из переменных.  Для более подробных
         разъяснений смотрите 2.5 и 2.8.




              4.2.  Обращение к переменной

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




              5.  ВЫРАЖЕНИЯ


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

              Выражение состоит из операций и операндов.


              5.1.  Синтаксис

              Синтаксис выражения в терминах РБНФ следующий:

         Expression            = SimpleExpression
                                 [ relation SimpleExpression ] .

         SimpleExpression      = [ '+' | '-' ] Term
                                 { AddOperator Term } .

         Term                  = Factor { MullOperator Factor } .

         Factor                = Constant |
                                 VariableReference |
                                 SetConstructor |
                                 FunctionCall |
                                 'not' Factor |
                                 '(' Expression ')' .

         relation              = '=' | '<>' | '<' | '<=' |
                                 '>=' | '>' | 'in' .

         AddOperator           = '+' | '-' | 'or' | 'xor' | '|' .

         MullOperator          = '*' | '/' | 'div' | 'mod' |
                                 'and' | '&' .

         Constant              = number | string | ConstIdent |
                                 'nil' .

         SetConstructor        = '[' [ SetElement
                                     { ',' SetElement } ] ']'.

         SetElement            = Expression [ '..' Expression ] .

         FunctionCall          = [ UnitIdent '.' ]
                                 FuncIdent [ '(' ActualParam
                                 { ',' ActualParam } ] .

         ActualParam           = Expression .

         32                                          UniPASCAL - Выражения
         -----------------------------------------------------------------

              5.2.  Операции

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

              5.2.1.  Арифметические операции

              Арифметические операции выполняются над целыми или веществен-
         ными операндами и порождают целый или вещественный результат.

              Унарные арифметические операции (знаки):

         Операция     Действие       Тип операнда     Тип результата
            +      тождественное   Integer или Real   тип операнда
            -     изменение знака  Integer или Real   тип операнда

              Бинарные арифметические операции:
         Операция     Действие      Тип операндов    Тип результата
            *         умножение    Integer или Real Integer или Real
            /         деление      Integer или Real       Real
           div        деление           Integer          Integer
           mod        остаток           Integer          Integer
            +         сложение     Integer или Real Integer или Real
            -         вычитание    Integer или Real Integer или Real

              ПРИМЕЧАНИЕ:  Символы '+', '-', '*' применяются и для обо-
         значения операции над множествами.

              ПРИМЕЧАНИЕ:  Здесь Integer обозначает все разновидности цело-
         го типа: Integer, ShortInt, Cardinal, Natural, ShortCard, LongInt.
              Если оба операнда одного и того-же типа, то результат тоже
         этого типа.  Если типы операндов различаются, тогда результат бу-
         дет наименьшего типа, включающего значения типов операндов.
         Например:  Если тип одного из операндов ShortInt, а тип другого
         - Natural, то тип результата будет Integer, потому что оба типа
         являются его диапазонами.

              Если в случае целочисленных операций оба операнда и верный
         результат находятся в диапазоне Min(LongInt)..Max(LongInt), то
         получается правильный результат.  Но результат выражения зависит
         еще от типа переменной, которой он присваивается.  Если результат
         выходит за границами ее типа, то ей присваивается неверное значе-
         ние.  Чтобы этого не получалось, необходимо знать ожидаемый ре-
         зультат вычисления выражения.

              Вычисление терма x/y будет ошибкой, если y равен нулю.
              Результат операций сложения, вычитания и умножения будет це-
         лого типа, если оба операнда - целого типа.  Если тип одного опе-
         ранда вещественный, то получается результат вещественного типа.
         Операции и стандартные функции, дающие вещественный результат,
         всегда следует считать приближенными, а не точными.  Их точность
         зависит от реализации.

         UniPASCAL - Выражения                                          33
         -----------------------------------------------------------------


              5.2.2.  Логические операции

              Логические операции:

         Операция     Действие      Тип операндов    Тип результата
           not    логическое "не"      Boolean          Boolean
           and    логическое "и"       Boolean          Boolean
           &      логическое "и"       Boolean          Boolean
           or     логическое "или"     Boolean          Boolean
           |      логическое "или"     Boolean          Boolean
           xor    логическое           Boolean          Boolean
                  исключающее "или"

              ПРИМЕЧАНИЕ:  Если после вычисления одного операнда операции
         'and' или 'or' резулЬтат уже известен, то значение второго операн-
         да не влияет на результат и поэтому не вычисляется.  Если необхо-
         димо чтобы значение второго операнда всегда вычислялось, нужно
         применять операции '&' и '|' соответственно.  Значения обоих опе-
         рандов указанных операций вычисляются до конца.



              5.2.3.  Операции над множествами

              Операции над множествами:

         Операция     Действие        Тип операндов    Тип результата
            +     объединение множеств   set of T         set of T
            -     разность    множеств   set of T         set of T
            *     пересечение множеств   set of T         set of T

              Оба операнда должны всегда относится к совместимым типам
         (см.  3.4).

              Получение результата подчиняется множественной логике:
              - значение C является элементом множества A + B, если C
         является элементом множества A или элементом множества B;
              - значение C является элементом множества A - B, если C
         является элементом множества A и не является элементом множества
         B;
              - значение C является элементом множества A * B, если C
         является элементом множества A и элементом множества B.

         34                                          UniPASCAL - Выражения
         -----------------------------------------------------------------


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

              Операции отношения:

         Операция  Действие   Тип операндов            Тип результата

           =       равенство  совместимый простой,         Boolean
                              ссылочный, множественный,
                              строковый, массив,
                              запись

           <>       неравенство совместимый простой,
                              ссылочный, множественный,    Boolean
                              строковый, массив,
                              запись

           <     меньше    совместимый простой,         Boolean
                              строковый

           <=            меньше    совместимый простой,         Boolean
                 или равно    строковый

           >     больше    совместимый простой,         Boolean
                              строковый

           >=            больше    совместимый простой,         Boolean
                 или равно    строковый

           <=         включение    совместимый множественный    Boolean
                 множеств

           >=         включение    совместимый множественный    Boolean
                 множеств

           in  принадлежность левый операнд должен быть    Boolean
                 множеству    ординального типа, правый
                              операнд должен быть мно-
                              жественного типа с совме-
                              стимым базовым типом лево
                              го операнда


         UniPASCAL - Операторы                                          35
         -----------------------------------------------------------------




              6.  ОПЕРАТОРЫ


              Операторы определяют алгоритм действия.  Перед любым операто-
         ром допускается метка, на которую можно ссылаться с помощью опера-
         тора перехода. Операторы объединяются в разделе операторов каждого
         блока.  Раздел операторов является составным оператором (Compound-
         Statement).

              Синтаксис:
         Statement = [ LabelRef ':' ] ( SimpleStatement |
                                        StructuredStatement ) .

         LabelRef       = Ident | IntNumber .

         StatementPart  = CompoundStatement .

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


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

              Простым называется оператор, в котором не включены как
         составные части другие операторы.

              Синтаксис:

         SimpleStatement = EmptyStatement |
                           AssignmentStatement |
                           ProcedureStatement |
                           GotoStatement .


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

              Пустой оператор (EmptyStatement) не содержит никаких символов
         и не определяет никаких действий.

              Синтаксис:

         EmptyStatement = .


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

              Оператор присваивания (AssignmentStatement) предназначен для
         замены текущего значения переменной на значение, полученное при
         вычислении выражения или для спецификации выражения, результат
         вычисления которого возвращается функцией.

         36                                          UniPASCAL - Операторы
         -----------------------------------------------------------------

              Синтаксис:

         AssignmentStatement = ( VariableIdent |
                                 FunctionIdent ) ':=' Expression .

              Значение выражения должно быть совместимо с типом переменной
         или типом идентификатора функции.


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

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

              Синтаксис:

         ProcedureStatement = ProcIdent [ ActualParameterList ] .


              6.1.4.  Оператор перехода.

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

              Синтаксис:

         GotoStatement = "goto" LabelRef .

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


              6.2.  Сложные операторы

              Сложные операторы (Structured statements) - это конструкции,
         состоящие из других операторов, причем эти операторы либо выпол-
         няются последовательно (составные операторы), либо - в зависимости
         от условия (условные операторы и операторы выбора), либо повторя-
         ются (операторы цикла), либо выполняются в некоторой расширенной
         области действия (scope) (оператор присоединения).
              Синтаксис:
         StructuredStatement = CompoundStatement |
                               ConditionalStatement |
                               RepetativeStatement |
                               WithStatement .

         UniPASCAL - Операторы                                          37
         -----------------------------------------------------------------


              6.2.1.  Последовательность операторов

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

              Синтаксис:

         StatementList = Statement { ';' Statement } .


              6.2.2.  Составной оператор

              Составной оператор (CompoundStatement) задает выполнение по-
         следовательности операторов (StatementList).  Слова begin и end
         выполняют роль операторных скобок.

              Синтаксис:

         CompoundStatement = 'begin' StatementList
                             'end' .


              6.2.3.  Условные и выбирающие операторы

              Эти операторы выбирают для выполнения одну (или никакую) свою
         компоненту.

              Синтаксис:

         ConditionalStatement = IfStatement | CaseStatement .



              6.2.3.1.  Условный оператор if

              Синтаксис:

         IfStatement = 'if' Expression 'then'
                            Statement
                        [ 'else' Statement ] .

         где Expression должно быть логическое выражение стандартного типа
         Boolean.
              Если логическое выражение имеет значение истина (TRUE), то
         выполняется оператор (Statement), следующий за словом then.  Если
         логическое выражение имеет значение ложь (FALSE), то выполняется
         (если существует) оператор (Statement), следующий за словом else.

              Примечание:  Синтаксическая двусмысленность конструкции:

         if Exp1 then if Exp2 then Stat1 else Stat2

         разрешается, считая, что она еквивалентна конструкции:

         38                                          UniPASCAL - Операторы
         -----------------------------------------------------------------

         if Exp1 then
            begin
              if Exp2 then
                 Stat1
              else Stat2
            end



              6.2.3.2.  Оператор варианта

              Оператор варианта (CaseStatement) содержит ординальное выра-
         жение (индекс варианта) (selector) и список операторов.  Перед
         каждым оператором списка стоит одна или несколько констант, отно-
         сящиеся к типу индекса варианта, или слово 'else', последованное
         двоеточием.

              Оператор варианта указывает, что необходимо выполнить опе-
         ратор, перед которым стоит константа, равная значению индекса ва-
         рианта.  Если ни перед одним оператором не стоит константа, равная
         этому значению, то выполняется оператор, который находится в Else-
         Part, если она существует; если нет ElsePart, то управление пере-
         дается оператору, следующему за телом оператора варианта.

              Синтаксис:

         CaseStatement = 'case' Selector 'of'
                            case { ';' case }
                          [ ElsePart ] [ ';' ]
                          'end' .

         Selector      = OrdinalExpression .

         Case          = Constant { ',' Constant } ':' Statement .

         ElsePart      = 'else' ':' Statement .



              6.2.4.  Операторы цикла

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

              Синтаксис:

         RepetitiveStatement = WhileStatement |
                               RepeatStatement |
                               ForStatement .

         UniPASCAL - Операторы                                          39
         -----------------------------------------------------------------


              6.2.4.1.  Циклы с предусловием

              Синтаксис:

         WhileStatement  = 'while' BooleanExpression 'do' Statement .

              BooleanExpression является выражением логического типа.  Опе-
         ратор (Statement) повторно выполняется до тех пор, пока выражение
         не даст значение ложь (FALSE).  Каждый раз вычисляется значение
         логического выражения перед выполнением оператора.  Если в самом
         начале значение логического выражения - ложь (FALSE), то оператор
         не выполняется вовсе.

              Оператор:  while B do S
              еквивалентен:  if B then begin S; while B do S end;


              6.2.4.2.  Циклы с постусловием

              Синтаксис:

         RepeatStatement = 'repeat' StatementList
                           'until' BooleanExpression .

              BooleanExpression является выражением логического типа.  По-
         следовательность операторов (StatementList) повторно выполняется
         до тех пор, пока выражение не даст значение истина (TRUE) (по
         крайней мере один раз она выполнится).  Значение логического
         выражения вычисляется после выполнения последовательности
         операторов.

              Оператор:  repeat S until B
              эквивалентен:  begin S; if not B then repeat S until B end;



              6.2.4.3.  Циклы for

              Цикл for указывает, что необходимо повторять выполнение
         оператора и одновременно присваивать переменной, называемой
         управляющей переменной цикла (ControlVariable), последовательно
         возрастающие (убывающие - если использовано зарезервированное
         слово downto) значения.

              Синтаксис:
         ForStatement    = 'for' ControlVariable ':=' InitialValue
                           ( 'to' | 'downto' ) FinalValue 'do'
                           Statement .

         ControlVariable = LocalVariableIdentifier .

         LocalVariableIdentifier = Identifier .

         InitialValue    = Expression .

         FinalValue      = Expression .

         40                                          UniPASCAL - Операторы
         -----------------------------------------------------------------

              Управляющая переменная должна быть описана в разделе описаний
         переменных блока, в разделе операторов которого находится данный
         оператор for.  Эта переменная должна относиться к ординальному ти-
         пу, совместимому с типами начального (InitialValue) и конечного
         значения (FinalValue).

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

              Оператор, содержащийся в цикле, выполняется один раз для каж-
         дого значения управляющей переменной из диапазона InitialValue ..
         FinalValue.  Если в цикле for использовано to, значение управляю-
         щей переменной увеличается на единицу после каждого повторения
         оператора.  Если InitialValue > FinalValue, то оператор не выпол-
         няется.  Если в цикле for использовано downto, значение управляю-
         щей переменной уменшается на единицу после каждого повторения опе-
         ратора.  Если InitialValue < FinalValue, то оператор не выполняет-
         ся.

              Никакой оператор внутри цикла не должен изменять значение
         управляющей переменной.

              После нормального окончания цикла for значение управляющей
         переменной неопределено.



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

              Синтаксис:

         WithStatement   = 'with' RecordVariableReference
                              { , RecordVariableReference } 'do'
                              Statement .

         RecordVariableReference = Identifier.

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

              Примечание:  Если имя некоторой переменной совпадает с именем
         поля переменной типа запись, то в рамках оператора присваивания
         with эта переменная становится недоступной.  Например:

         UniPASCAL - Операторы                                          41
         -----------------------------------------------------------------

         var
            Field: integer;
            Rec: record
                 Field, b: real;
                 end;

         (* ................... *)

         with  Rec  do begin
           Field:= 1;
         end;

              В этом фрагменте программы значение 1 присваивается полю
         Field типа Real переменной Rec, а не целой переменной Field.
              После выхода из оператора with целая переменная Field снова
         становится доступной.

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

              Запись:  with r1, r2, ...., rn do .......
              эквивалентна:
                            with r1 do
                              with r2 do
                                ...........
                                  with rn do ........ .

         42                                          UniPASCAL - Операторы
         -----------------------------------------------------------------

         UniPASCAL - Процедуры и функции                                43
         -----------------------------------------------------------------



              7.  ПРОЦЕДУРЫ И ФУНКЦИИ


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


              7.1.  Описания процедур

              Описание процедуры вводит идентификатор процедуры и ставит в
         соответствие этому идентификатору некоторый блок и, необязательно,
         список формальных параметров.  Этот идентификатор называется име-
         нем процедуры.

              Синтаксис:

         ProcDecl =      ProcHeading ';' (ProcBody | Directive)
                         ';' .

         ProcHeading =   [ 'segment' ]
                         'procedure' ProcIdent [ FormalParamsList ] .

         ProcIdent =     Ident.

         Directive =     'forward' | 'external' .

         ProcBody =      Block .

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

              Процедура может быть описана с помощью одного единственного
         описания, состоящего из заголовка процедуры и ее телa (ProcBody).
         Это самый распространенный способ.  Но есть и другие способы -
         опережающее описание и описание внешнoй процедурой.

              Когда используется способ опережающего описания (ForwardDe-
         claration), процедуре дается два описания:  первое описание состо-
         ит из заголовка процедуры и директивы forward, а второе описание,
         которое должно находится в том же разделе описаний процедур и
         функций, лишь идентифицирует процедуру и содержит ее тело.  Во
         втором описании список формальных параметров можно не указывать.
         Но если указан, то должен совпадать со списком формальных параме-
         тров первого описания.

         44                                UniPASCAL - Процедуры и функции
         -----------------------------------------------------------------


              Описание внешних процедур позволяет программисту использовать
         процедуры и функции, написанные на другом языке программирования и
         оттранслиранные отдельно.  Внешний код должен быть связан с про-
         граммой при помощи {$L filename } - директивы.

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

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

              Для вызова описанной процедуры используется оператор процедуры.

              Синтаксис:

         ProcedureStatement = [ UnitIdent '.']
                              ProcIdent [ ActualParameterList ] .

              Он состоит из идентификатора процедуры (ProcIdent), к которо-
         му необходимо обратиться и, если необходимо, списка фактических
         параметров (ActualParameterList).


              7.2.  Описания функций

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

              Синтаксис:

         FuncDecl = FuncHeading ';'( FuncBody | Directive ) ';' .

              Заголовок функции (FuncHeading) определяет имя функции, тип
         результата и список формальных параметров.

              Синтаксис:
         FuncHeading = [ 'segment' ] 'function' FuncIdent
                       [ FormalParamsList ]':' ResultType .

         ResultType  = SimpleType | Pointer .

         FuncBody    = Block .

              Тип результата (ResultType) определяет тип значения, возвра-
         щаемого функцией после ее выполнения.  Этот тип может быть простой
         (ординальный или вещественный) или тип указатель.

         UniPASCAL - Процедуры и функции                                45
         -----------------------------------------------------------------


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



              7.3.  Параметры

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

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

              В качестве параметра стандартной функции SizeOf можно задать
         не только переменные разного типа, но и идентификаторы описания
         типа.  Функция возвращает длину этого объекта.
              Например, SizeOf(integer) дает результат 2.  Здесь integer -
         имя стандартного типа integer, а результат - длина внутренного
         представления этого типа в байтах.

              Если дано описание:
         type
            Date = record
                     month: 1..12;
                     day: 1..31;
                     year: cardinal;
                     end;
          var
             d: Date;

              можно указать в качестве параметра функции SizeOf как иденти-
         фикатор типа Date, так и идентификатор переменной d: SizeOf(Date);
         SizeOf(d).
              В обаих случаях возвращаемый результат один и то же - равен
         6, потому что запись неупакованная.  Если при описании типа доба-
         влено слово packed, то возвращается результат 4.

              Исключения от правил передачи параметров являются не процеду-
         рами или функциями, а конструкциями языка.  Они описаны в разделе
         стандартных процедур и функций.

         46                                UniPASCAL - Процедуры и функции
         -----------------------------------------------------------------


              7.3.1.  Списки формальных параметров

              Синтаксис:

         FormalParamsList = '(' ParamDecl { ',' ParamDecl } ')' .

         ParamDecl        = [ 'var' ] IdentList ':' TypeIdent |
                            var IdentList .

         TypeIdent = Ident.

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


              7.3.1.1.  Формальные параметры-значения

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

              Соответствующий формальному параметру - значению фактический
         параметр в операторе процедуры или при обращении к функции может
         быть выражением и не должен быть типа файл.

              Фактический параметр должен соответствовать по типу формаль-
         ному параметру-значению.



              7.3.1.2.  Формальные параметры-переменные

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

              Тип фактического параметра должен быть идентичным типу фор-
         мального параметра.
              Переменные типа файл можно передавать в качестве параметров
         только как параметры-переменные.

              Компоненты упакованного типа нельзя сопоставлять с
         формальными параметрами-переменными.

         UniPASCAL - Процедуры и функции                                47
         -----------------------------------------------------------------


              7.3.1.3.  Формальные нетипизированные параметры-переменные

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

              Например, если дано описание:

         function Equal(var Source, Dest; Size: Cardinal):
         boolean;
           const
             MaxInt = Max(Integer);
           type
             Bytes = packed array [0..MaxInt] of byte;
           var
             N: Cardinal;
         begin N:= 0;
           while (N < Size) and ( Bytes(Dest)[N] =
         Bytes(Source)[N] ) do
           Inc(N);
           Equal:= N = Size;
         end; { Equal }

              Эту функцию можно применять для сравнения любых переменных
         любой длины.

              Если даны описания:
         type
           Vector = array [1..10] of integer;
           Point = record
                     x, y: integer;
                   end;
         var
           v1, v2: Vector;
           p: point;
           i: integer;

            то можно написать:

         if Equal(v1, v2, SizeOf(Vector)) then
            { ............................. }
            { Здесь сравниваются все компоненты переменных. }

         if Equal(v1[1], v1[6], SizeOf(Integer)*5) then
            { ............................. }
            { Здесь сравниваются первые 5 компонент переменной v1 с
              вторыми 5 компонентами }

         if Equal(v1, p, SizeOf(point)) then
            { ............................. }
            { Здесь сравниваются переменные разного типа и
              разной длины }

         48                                UniPASCAL - Процедуры и функции
         -----------------------------------------------------------------


              7.3.2.  Списки фактических параметров

              Список фактических параметров в операторе процедуры или опи-
         сании функции определяет фактические параметры, которые при выпол-
         нении процедуры или функции должны быть подставлены в качестве
         формальных параметров.  Если процедура или функция не имеет спис-
         ка формальных параметров, то не должен быть и список фактических
         параметров.

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

              Компоненты упакованного типа нельзя сопоставлять с формальны-
         ми параметрами-переменными.

              Если тип формального параметра-переменной word или longword,
         то он может быть сопоставлен с фактическом параметром любого типа,
         длина которого равна длине типа формального параметра (2 и 4 бай-
         та, соответственно).

              Синтаксис:
         ActualParameterList='(' ActualParam { ',' ActualParam } ')' .

         ActualParam =   Expression | VariableRef.

         UniPASCAL - Модули                                             49
         -----------------------------------------------------------------




              8.  MОДУЛИ

              В UniPascal-е предусмотрена возможность, которой нет в стан-
         дартном Pascal-е - возможность раздельной компиляции.

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

              Для устранения указанного недостатка в UniPascal-е предусмо-
         трена еще одна конструкция языка - модули (units).

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

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

              Во время трансляции импортирующей программы компилятор должен
         иметь доступ к описаниям объектов ранее откомпилированных модулей,
         из которых происходит импорт.  Этот механизм отличает раздельную
         компиляцию от независимой компиляции.  Любой вспомагательнным мо-
         дуль можеть, в свою очередь, импортировать объекты из других моду-
         лей.  Следовательно, программа может представлять собой целую йе-
         рархию модулей.  Главная программа имеет самый высший уровень, а
         модули, которые не импортируют объектов - самый низший.

              Чтобы компилятор знал о используемых модулях, список их иден-
         тификаторов дается как UsesClause в тексте главной программе.

              Синтаксис:

         Unit =  'unit' UnitIdent ';'
                InterfacePart
                ImplementationPart .

         UnitIdent =     Ident .

         InterfacePart = 'interface'
                         [ UsesClause ]
                         InterfaceDecl .

         InterfaceDecl = { ConstDecl | TypeDecl | VarDecl | PFdecl }.

         50                                             UniPASCAL - Модули
         -----------------------------------------------------------------

         ImplementationPart=     'implementation'
                             [ UsesClause ]
                             (( Declarations 'end') | Block | 'end') .


              В UniPascal-е текст модулей состоит из двух разделов - раздел
         описаний (InterfacePart) и раздел реализации (ImplementationPart).
         Чтобы не компилировать всегда обе части одновременно, предусмотре-
         на возможность их раздельной компиляции.  Эти два раздела обосо-
         бляются как два модуля - модуль описаний (InterfaceUnit) и модуль
         реализации (ImplementationUnit).



            8.1. Раздел описаний

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

              Оба модуля можно компилировать отдельно и поэтому называются
         единицами компиляции.  Единица компиляции - это все, что может
         быть компилировано самостоятельно:  программа (Program), модуль
         (Unit), модуль описаний (InterfaceUnit), модуль реализации
         (ImplementationUnit).

              Синтаксис единиц компиляции:

         Compilation = ( Program | Unit | InterfaceUnit |
                         ImplementationUnit ) '.'.


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

              Синтаксис модуля описаний;

         InterfaceUnit = 'interface' 'unit' Ident ';'
                         [ UsesClause ]
                         InterfaceDecl
                         'end'.

         InterfaceDecl = { ConstDecl | TypeDecl | VarDecl | PFdecl }.

              Компилированный раздел (модуль) описаний сохраняется в файле
         с разширением имени '.sym'

         UniPASCAL - Модули                                             51
         -----------------------------------------------------------------


              8.2.  Раздел реализации

              Компилированный раздел (модуль) реализации сохраняется в
         файле с разширением имени '.bdy'

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

              Синтаксис модуля реализации:  следующий:

         ImplmentationUnit = 'implementation' 'unit' Ident ';'
                             [ UsesClause ]
                             Block.

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

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




              8.3.  Особенности

              Если одинаковые идентификаторы описаны в главной программе и
         в некотором модуле, то доступным является идентификатор, описанный
         в главной программе. Чтобы сделать доступным идентификатор,
         описанный в модуле, его именем должно предшествовать имя модуля и
         точка ('.'). Например, если идентификатор Id, а модуль Mo, то для
         использования идентификатора, описанного в модуле, следует писать
         Mo.ID

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

              При выполнении программы все модули, из которых она импорти-
         рует объекты, должны быть в текущей директории.

         52                                             UniPASCAL - Модули
         -----------------------------------------------------------------

              8.4.  Пример использования модулей

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

         unit Stack; interface
           var full:  boolean;
               empty: boolean;
           procedure push(x: word);
           function  pull: word;
         implementation
           const StackSize = 100;
           type StackIndex = 0..StackSize;
           var curr: StackIndex;
               StackArray: array [StackIndex] of word;
           procedure push(x: word);
           begin
           if not full
             then begin StackArray[curr]:= x;
                  Inc(curr);
                  end;
           full:= StackSize <= curr;
           empty:= false;
           end; { push }
           function pull: word;
           begin
           if not empty
             then begin Dec(curr);
                  pull:= StackArray[curr];
                  end;
           empty:= curr = 0;
           full:= false;
           end; { pull }
         begin
           curr:= 0; full:= false; empty:= true;
         end. { Stack }

              А вот и программа, использующая модуль Stack.

         program UseStack;
           uses Stack;
           var i: integer;
         begin
           i:= 0;
           while not full do
             begin push(i);
             inc(i);
             end;
           while not empty do
             writeln(pull);
         end.

         Компилятор UniPASCAL                                           53
         -----------------------------------------------------------------



              9.  КОМПИЛЯТОР UniPASCAL

              9.1. Вызов компилятора

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

                             UPC <имя_исходного_файла>

              Если имя исходного файла не содержит расширение, по умолчанию
         считается, что расширение .PAS.

              Основным результатом работы компилятора является файл, содер-
         жащий выполнимый вид компилированной программы.  Имя файла соот-
         ветствует имени паскальской программы с расширением .PGM.

              При вызове компилятора можно дополнительными параметрами
         определить один или более идентификаторов условной компиляции (об
         условной компиляции смотрите ниже).  Дополнительные параметры вво-
         дятся в виде /Dxxx, где ххх - идентификатор условной компиляции.
         Каждый дополнительный параметр соответствует одной строке {$define
         xxx}, введенной в начале программы.

              Пример:  допустим, что необходимо компилировать исходный файл
         MY_Prog.pas и при этом определить идентификатор условной компиля-
         ции Comp_id.  Вызов компилятора следует осуществить командой:

                               UPC my_prog /Dcomp_id





              9.2.  Стандартные расширения имен файлов

              При разработке компилятора UniPASCAL приняты следуюшие стан-
         дартные (воспринимаемые по умолчанию) имена файлов:

              PAS - расширение имен исходных файлов;

              PGM - расширение имен файлов, содержащих выполнимые
         программы;

              SYM - расширение имен файлов, содержащих интерфейсные части
         компилируемых модулей;

              BDY - расширение имен файлов, содержащих тела (implementation)
         компилируемых модулей;

         54                               UniPASCAL - Компилятор UniPASCAL
         -----------------------------------------------------------------



              9.3.  Внутренное представление данных

              Все переменные располагаются в памяти на границе слова (2
         байта) и имеют длину, кратную 16 битам.  Исключение составляют
         элементы массивов или записей, для которых прямо указано пакети-
         рование данных. Строки символов всегда пакетированы.

              Все простые переменные, исключая переменных типа указателя,
         записаны в памяти в порядке младший байт - старший байт. Указатели
         записываются в порядке старший байр - младший байт.

         UniPASCAL - Управление компиляцией                             55
         -----------------------------------------------------------------




              10.  УПРАВЛЕНИЕ КОНПИЛЯЦИЕЙ

              Процесс компиляции исходного текста управляется при помощи
         директив компилятору. Директива вводится в исходный текст в виде
         комментария со следующим специальным синтаксисом:

           CompilerOption =    '{$' directive '}' | '(*$' directive '*)'

         т.е. - первым символом комментарной формы записи должен быть знак
         доллара "$".

              ВНИМАНИЕ!  В одной строке исходного текста (в одной коммен-
         тарной форме) может быть записана только одна директива.  Все на-
         ходящееся после первого пробела в комментарной форме считается
         нормальным комментарием.  Исключением состовляют т.н.  "переключа-
         ющие" директивы (см.  ниже).  Для них допускается ввод более одной
         директивы в одной форме, но при условии, что директивы разделены
         запятыми БЕЗ ПРОБЕЛОВ.  Каждая директива должна быть записана пол-
         ностью в одной строке (в одной комментарной форме).

              Если в исходном тексте найден текст несуществующей директивы,
         компилятор UniPASCAL выдает соответствующее сообщение, но не воз-
         никает ситуация ОШИБКА.

              Директивы UniPASCAL-я можно разделить на три группы:

              - ПЕРЕКЛЮЧАЮЩИЕ директивы - директивы включения или выключе-
         ния определенных действий, определенных возможностей компилятора.
         Переключающие директивы состоят из однобуквенного идентификатора
         директивы и знака "+" (плюс - включить) или "-" (минус - выклю-
         чить).  Между идентификатором и знаком не должны находиться другие
         символы.  Как уже было подчеркнуто, в одной директивной форме мож-
         но записать несколько переключающих директив, разделенных запятыми
         без пробелов.  Например, строки
                                       {$I+}
                                       {$R-}
         можно заменить строкой
                                      {I+,R-}
         но не и строкой
                                      {I+, R-}

              В последнем случае текст "R-" будет считаться нормальным ком-
         ментарием.

              - директивы С ПАРАМЕТРОМ - после однобуквенного идентификато-
         ра директивы следует ввести (через пробел) соответствующий пара-
         метр выполнения директивы;

              - директивы УСЛОВНОЙ КОМПИЛЯЦИИ - в качестве идентификатора
         променяется ключевое слово.  Часть директив этой группы предусма-
         тривает ввод соответствующих параметров.

         56                             UniPASCAL - Управление компиляцией
         -----------------------------------------------------------------


              10.1.  Переключающие директивы

              Внимание!  При описании переключающих директив в заголовке
         указан знак ("+" или "-" - "включить" или "выключить", соответ-
         ственно), который является значением ПО УМОЛЧАНИЮ.



              10.1.1.  I+   - генерация кода проверки результата выполнения
                              операции ввода/вывода

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

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



              10.1.2.  R+   - генерация кода проверки во время выполнения
                              программы соблюдения границ диапазона.

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

              При выключенном состоянии компилятор проверяет только значе-
         ния констант и константных выражений.



              10.1.3.  W+   - выдача диагностического сообщения о резуль-
                              татах компиляции оператора, перед которым
                              находится директива.


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

              Действие директивы распространяется только на один - следую-
         щий за директивой - оператор.  После его компиляции выдача сообще-
         нии включается автоматически.  В случае необходимости выключить
         сообщения о нескольких последовательных операторах, рекомендуем
         объединить их конструкцией begin ...  end в составной оператор и
         записать директиву {$W-} перед ним.

         UniPASCAL - Управление компиляцией                             57
         -----------------------------------------------------------------


              10.1.4.   Y+   - интерпретация символьной последовательности
                              (*) в качестве законченного комментария.

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

                                  (*) writeln; (*)

              Если исполнена директива Y-, то для компилятора фрагмент
         представляет собой комментарий ") writeln (".  Если выполнена
         директива Y+, то фрагмент представляет оператор writeln между
         двумя комментариями. Таким образом получаем возможность
         осуществить условную компиляцию типа:

                             {$ifOpt Y+} .... {$endif}

              Рассмотрим фрагмент

                            (*) writeln; {*) readln; {*}

              Если выполнена директива Y-, то фрагмент будет интерпретиро-
         ван в качестве последовательности:

                 комментарий           ") writeln; {"
                 оператор                 readln;
                 комментарий                "*"

              Если выполнена директива Y+, то фрагмент будет интерпретиро-
         ван в качестве последовательности:

                 комментарий                (*)
                 оператор                 writeln;
                 комментарий           "*) readln; {*"

              Таким образом директива позволяет осуществить условную ком-
         пиляцию типа:

                        {$ifOpt Y+} ... {$else} ... {$endif}

         58                             UniPASCAL - Управление компиляцией
         -----------------------------------------------------------------


              10.2.  Директивы с параметром

              Единственной директивой с параметром транслятора UniPASCAL
         является директива включения в исходный файл дополнительного
         файла.

              Синтаксис: {$I <полное_имя_включаемого_файла>}

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

                - вложение директивы допускается до четвертого уровня;
                - тело каждой процедуры и функции должно находится
         полностью в одном файле;
                - один комментарий должен находиться полностью в одном
         файле.



              10.3.  Директивы условной компиляции

              Идея условной компиляции состоит в том, что определенный
         фрагмент исходной программы компилируется только в случае
         выполнения некоторого условия. Идея и соответствующие механизмы
         хорошо известны программистам, имеющим опыта работы на языке
         ассемблера или Turbo Pascal для компьютеров типа IBM-PC-XT/AT.



              10.3.1. Директивы DEFINE и UNDEF

              Директивы предназначены для определения и удаления
         идентификаторов условной компиляции (ИУК) и имеют синтаксис:

                   {$define <идентификатор_условной_компиляции>}
                   {$undef  <идентификатор_условной_компиляции>}

              Одним из возможных условий компиляции программного фрагмента
         является определение или неопределение ИУК - т.е. является или не
         является указанный идентификатор идентификатором условной
         компиляции.

              В одной программе могут быть определены одновременно не более
         восьми идентификаторов условной компиляции.

              ИУК рассматриваются компилятором совершенно отдельно от
         остальных идентификаторов в тексте программы. Поэтому ИУК может
         совпадать по написанию с другим, нормальным идентификатором в
         программе.

              Для компилятора UniPASCAL по умолчанию определен
         идентификатор условной компиляции UniPas.

         UniPASCAL - Управление компиляцией                             59
         -----------------------------------------------------------------


              10.3.2.  Директивы IFDEF, IFNDEF, IFOPT, ELSE и ENDIF

              Условная компиляция осуществляется при помощи конструкции
         типа:

         {$IFxxx <условие>}
            {компилируемый в случае выполнения условия фрагмент программы}
         {$ENDIF}

         или

         {$IFxxx <условие>}
            {компилируемый в случае выполнения условия фрагмент программы}
         {$ELSE}
            {компилируемый в случае невыполнения условия фрагмент}
         {$ENDIF}

         где IFxxx одна из директив IFDEF, IFNDEF или IFOPT.

              При применении директивы IFDEF условие представляет собой
         идентификатор условной компиляции и считается выполненным, если
         идентификатор определен (см.  директивы DEFINE, UNDEF).


              При применении директивы IFNDEF условие представляет собой
         идентификатор условной компиляции и считается выполненным, если
         идентификатор НЕ определен (см.  директивы DEFINE, UNDEF).

              При применении директивы IFОРТ условие представляет собой
         идентификатор переключающей директивы и соответствующий ключ ("+"
         или "-") и считается выполненным, если директива находится в
         указанном состоянии (см. 10.1.).

              Поясним применение директив на следующем примере.  Допустим,
         что необходимо выдать сообщение, если выключена генерация кода
         проверки результата операции ввода/вывода, а также сообщение о том
         определен или нет идентификатор Turn_on.  Тогда возможна следующая
         реализация:

         .................
         {$IFOPT I-}
            writeln("Проверка результата ввода/вывода не производится!")
         {$endif}
         {$IFDEF turn_on}
            writeln("Идентификатор Turn_on определен!")
         {$else}
            writeln("Идентификатор Turn_on неопределен!")
         {$endif}
         .........

         60              UniPASCAL - Диагностические сообщения компилятора
         -----------------------------------------------------------------


              11.  ДИАГНОСТИЧЕСКИЕ СООБЩЕНИЯ КОМПИЛЯТОРА

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

              - ошибки, которые не влияют на процесс компиляции - при обна-
         ружении таких ошибок компилятор выводит предупредительное сообще-
         ние и продолжает свою работу, генерируя код и после места ошибки.
         Ошибки этой группы имеют номера с 1 по 13;

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

              - фатальные ошибки - после обнаружения такой ошибки компиля-
         ция прекращается.  Ошибки этой группы имеют номера с 240 по 255.

              Если когда нибуть во время компиляции получите диагностичес-
         кое сообщение с номером ошибки вне интервала [1..255] настойчиво
         просим выслать в адрес НИПЛ"Програмно осигуряване" программный
         текст в процессе компиляции которого получено такое сообщение.

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

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

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




              11.1.  Ошибки, не влияющие на процесс компиляции


         1: Compiler directive must not exceed source line
            Директива управления компиляцией должна полностью помещаться в
            одной строке исходного текста

         2: Invalid compiler directive
            Несуществующая директива управления компиляцией

         3: Error in compiler directive
            Ошибка в директиве управления компиляцией
               Например, {$R*} вместо{$R+}

         UniPASCAL - Диагностические сообщения компилятора              61
         -----------------------------------------------------------------


         4: This directive must appear at top of program
            Эту директиву можно ввести только в начале программы
               (до появления ключевого слова program)

         5: Pointer must be dereferenced probably
            Вероятное использование переменной типа указателя
                (но не обнаружен разделитель ^)

         7: Word/Byte standard proc/func mismatched
            Изпользована стандартная процедура или функция для работы с
            байтами, но ее параметры не пакетированы, или наоборот.

         8: Fill with too large size
            Изпользована  процедура FillChar или FillWord и заданная длина
            превышает длину заполняемого участка.

         13: Invalid character in text
             Неправильный символ в тексте программы.
               Вероятнее всего найден символ с ASCII-кодом меньше $20 или
               больше $7Е. Символ игнорируется.





              11.2.  Нефатальные ошибки


         14: Digit expected
             Ожидается (но не найдена) цифра.

         15: Integer [0..255] expected
             Ожидается (но не найдено) целое число в диапазоне [0..255].

         16: Integer expected
             Ожидается (но не найдено) целое число.

         17: 'program' expected
             Ожидается (но не найдено) ключевое слово "program"

         18: 'unit' expected
             Ожидается (но не найдено) ключевое слово "unit"

         19: 'interface' expected
             Ожидается (но не найдено) ключевое слово "interface"

         20: 'implementation' expected
             Ожидается (но не найдено) ключевое слово "implementation"

         21: 'begin' expected
             Ожидается (но не найдено) ключевое слово "begin"

         22: 'do' expected
             Ожидается (но не найдено) ключевое слово "do"

         62              UniPASCAL - Диагностические сообщения компилятора
         -----------------------------------------------------------------


         23: 'downto' expected
             Ожидается (но не найдено) ключевое слово "downto"

         24: 'end' expected
             Ожидается (но не найдено) ключевое слово "end"

         25: 'of' expected
             Ожидается (но не найдено) ключевое слово "of"

         26: 'then' expected
             Ожидается (но не найдено) ключевое слово "then"

         27: 'to' expected
             Ожидается (но не найдено) ключевое слово "to"

         28: 'until' expected
             Ожидается (но не найдено) ключевое слово "until"

         29: 'procedure' or 'function' expected
             Ожидается (но не найдено) ключевое слово "procedure" или
             "function"

         32: Error in integer or real number
             Ошибка в численной константе (целой или реальной)

         36: Label (integer or identifier) expected
             Ожидается (но не найдена) метка (идентификатор или число)

         37: ':' or ',' expected
             Ожидается (но не найден) символ ":" или ","

         38: 'begin' or declarations expected
             Ожидается (но не найдено) ключевое слово "begin" или
             определение

         39: '=' expected
             Ожидается (но не найден) символ "="

         40: ':=' expected
             Ожидается (но не найден) символ ":="

         41: '..' expected
             Ожидается (но не найден) символ ".."

         42: '.' expected
             Ожидается (но не найден) символ "."

         43: '[' expected
             Ожидается (но не найден) символ "["

         44: ']' expected
             Ожидается (но не найден) символ "]"

         UniPASCAL - Диагностические сообщения компилятора              63
         -----------------------------------------------------------------


         45: '(' expected
             Ожидается (но не найден) символ "("

         46: ')' expected
             Ожидается (но не найден) символ ")"

         47: ';' expected
             Ожидается (но не найден) символ ";"

         48: ':' expected
             Ожидается (но не найден) символ ":"

         49: ',' expected
             Ожидается (но не найден) символ ","

         50: Identifier expected
             Ожидается (но не найден) идентификатор

         51: Error in declaration part
             Ошибка в части определения (декларативной части)

         52: Identifier redeclaration
             Попытка повторного определения идентификатора

         53: Error in type
             Ошибка при определении типа

         54: Error in simple type
             Ошибка в простом типе (simple type)

         55: String size in range '1..255' expected
             Ожидается (но не найдена) целочисленная константа в диапазоне
             [1..255] для определения длины строки символов

         56: Subrange bounds must be scalar
             Границы диспазонного типа должны быть простого типа

         57: Low bound exceeds high bound
             Нижняя граница диапазонного типа больше верхней границы.

         58: Incompatible subrange types
             Несовместимые типы границ

         59: Undeclared forward procedure or function
             Неопределенная forward-процедура или функция

         60: Unresolved forward reference type
             Неразрешенная ссылка на forward-тип
               Вероятнее всего попытка использовать в качестве базы
               переменной типа указателя тип, который не описан в той-же
               самой type-секции.

         61: This type can't be used as an index type
             Этот тип не может быть использован в качестве индексного типа

         64              UniPASCAL - Диагностические сообщения компилятора
         -----------------------------------------------------------------

         62: Files not allowed here
             Указание файлов здесь не разрешено.
               Вероятнее всего попытка указать файл в качестве элемента
               массива или записи.

         63: Previous declaration was not forward
             Предыдущее определение не типа forward.
               Попытка применить в качестве идентификатора процедуры или
               функции уже определенный идентификатор

         64: A forward declared function type mismatch
             Ошибка при определении типа forward-заданной функции

         65: Function type must be scalar, subrange or pointer
             Тип функции должен быть простой, диапазон или указатель
               (в частности не разрешены массивы, записи или строки).

         66: Missing result type in function declaration
             При определении функции не указан тип результата

         67: Interface procedure redeclaration
             Попытка повторного определения интерфейсной процедуры

         68: Forward redeclaration
             Попытка повторного forward-определения процедуры

         71: Header doesn't match previous declaration
             Заголовок (процедуры или функции) не соответствует ранее
             данному определению

         72: Error in parameter list
             Ошибка в списке параметров

         73: Only variable file parameters allowed
             В качестве параметров файла разрешено использование только
             переменных

         74: External files allowed only in programs
             Указание внешних файлов разрешено только в заголовках программ
             (но не и модулей)

         75: Not a standard file
             Заданный параметр не является стандартным файлом

         76: Tag field type must be scalar or subrange
             Переменное поле файла (tag field) должно быть простого типа

         77: Incompatible with tag field type
             Несоответствие типу переменного поля (tag field)

         78: Error in field list
             Ошибка в списке полей записи

         79: Set base type must be subrange
             Базовый тип множества должен быть простым

         UniPASCAL - Диагностические сообщения компилятора              65
         -----------------------------------------------------------------

         80: Forward procedures and functions not allowed in interface
             Не разрешено опережающее (foward) определение процедур и
             функции в интерфейсной части модуля

         81: Forward declaration was/wasn't segment
             Опережающее определение процедуры или функции не соответствует
             текущему в отношении сегментности (создании перекривающих
             oveflay процедур)

         84: Labels must be in the range 0..9999
             Метки должны быть в диапазоне [0..9999]

         85: Reserved name used as a label
             Попытка применить зарезервированное имя в качестве метки

         86: Label redeclaration
             Попытка повторного определения метки

         87: Labels not allowed in interface part
             Использование меток не разрешено в интерфейсных частях модулей

         95: Undefined label
             Неопределенная метка

         96: Undeclared label
             Недекларированная метка

         97: Label redeclaration
             Попытка порторной декларации метки

         98: Label expected
             Ожидается (но не найден) метка

         99: Illegal label
             Неправильная метка

         100: Error in factor
              Ошибка в арифметическом или логическом выражении
              (factor по РБНФ).

         101: Error in variable
              Ошибка при применении переменной

         102: Boolean expected
              Ожидается (но не найдено) выражение типа Boolean

         103: Scalar or subrange type expected
              Ожидается (но не найдено) выражение типа Scalar или subrange

         104: Duplicate constant in case statement
              Дублирование константы в case-операторе

         105: Constant type incompatible with selecting expression
              Тип константы не совпадает с типом выражения выбора в
              case-операторе

         66              UniPASCAL - Диагностические сообщения компилятора
         -----------------------------------------------------------------

         106: Scalar or SubRange expected
              Ожидается выражение типа Scalar или SubRange

         107: Type of set elements must be compatible
              Элементы множества должны быть совместимыми по типу

         108: Lo bound exceeds hi bound
              Нижная граница превышает верхную

         109: Too many labels in one statement
              Много меток в одном операторе
                При необходимости применяйте пустой оператор. Например,
                вместо неправильного Lab1: Lab2: Lab3: ...
                используйте правильное Lab1: ; Lab2: ; Lab3: ...

         110: Boolean expression expected
              Ожидается (но не найдено) выражение типа Boolean

         111: FOR loop control variable
              Переменная управления цикла FOR
              (должна быть локальной для текущей процедуры)

         112: Illegal type of FOR loop control variable
              Неправильный тип переменной управления FOR-цикла

         113: Illegal type of expression
              Неправильный тип выражения

         114: Type conflict (incompatible with control loop variable)
              Несовпадение типов (тип выражение не сопадает с типом
              переменной управления цикла)

         115: Structure is not byte packed
              Структура не является пакетированной на границе байта

         116: Incompatible with left side variable
              Несовместимость (по типу) с переменной левой части оператора
              присваивания

         117: Goto over EXIT:
              Переход через EXIT
              (Попытка при помощи GOTО передать управление из завершающей
              части процедуры, функции, программы или модуля в тело)

         118: Illegal type of variable
              Неправильный тип переменнной

         121: No such variant in this record
              Нет такого варианта в этой записи

         123: Incompatible with tag field
              Несовместимость с переменным полем записи

         139: Type of variable is not a pointer
              Переменная не является указателем

         UniPASCAL - Диагностические сообщения компилятора              67
         -----------------------------------------------------------------

         140: Type of variable is not an array
              Переменная не является массивом

         141: Index type must be scalar or subrange
              Тип индекса должен быть scalar или subrange

         142: Index type incompatible with declaration
              Тип индекса не совпадает с декларацией

         143: Type of variable is not a record
              Тип переменной не является записью

         144: No such field in this record
              Нет такого поля в этой записи

         145: Expression is not of set type
              Выражение не обладает типом множества

         146: String constant has differ length
              Константа типа строки имеет неправильную длину

         148: Can't handle this packed file
              Невозможно обработать этот пакетированный файл

         149: Text files not allowed
              Не разрешено применение текстового файла (в качестве
              параметра)

         150: Assignment to this function not allowed here
              Не разрешено в этом месте присваивать значение этой функции
              (Вероятнее всего нарушение правил вложенности)

         151: Result value is not allowed in procedures
              Процедуры не имеют имплицитного результата

         152: Must specify return value for functions
              Возвращаемое функцией значение должно быть определено
              (хотя бы так return())

         153: Untyped file expected
              Файл должен быть нетипизированным

         155: File variable expected
              Ожидается (но не найдена) переменная типа файла

         156: Type of expression is not compatible with expected type
              Неправильный тип выражения

         157: Error in type standard procedure parameter
              Неправильный тип параметра стандартной процедуры

         158: Illegal type operands
              Неправильный тип операндов

         68              UniPASCAL - Диагностические сообщения компилятора
         -----------------------------------------------------------------

         159: Type conflict of operands
              Несовместимые по типу операнды

         160: Test on equality allowed only
              Разрешена только проверка на равенство

         161: Number of parameter does not agree with declaration
              Число параметров не совпадает с заданным в декларации

         162: Actual parameter must be a variable
              Фактический параметр должен быть переменной

         163: Incompatible with formal parameter's type
              Несоответствие типу формального параметра

         164: Scalar or subrange type expected
              Необходим тип scalar или subrange

         165: Incompatible with parameter's size
              Несовместимость с размером (формального) параметра

         166: Strict inclusion not allowed
              Проверка на стргое включение не разрешена

         170: Typed file expected
              Ожидается переменная типа типизированного файла

         171: Integer expression expected.
              Ожидается целочисленное выражение

         172: Can't read or write variables of this type
              Невозможно читать или писать переменные этого типа
                 Вероятнее всего попытка применения массива или записи в
                 операторах read, readln, write, writeln. Каждый элемент
                 должен быть обработан в отдельности.

         173: Text file expected (readln, writeln)
              Ожидается переменная типа текстового файла (для операторов
              readln, writeln)

         183: Error in factor (bad expression)
              Ожибка в факторе (неправильное выражение)

         184: Incompatible or illegal type of operand
              Несовместимый или неправильный тип операндов
              (бинарной опеарции)

         185: Division by zero
              Нулевое значение знаменателя

         186: Illegal type of constant
              Неправильный тип константы

         187: Constant out of range
              Недопустимое значение константы

         UniPASCAL - Диагностические сообщения компилятора              69
         -----------------------------------------------------------------


         190: Subrange of LongInt not supported
              Настоящая версия не позволяет применение диапазона типа
              LongInt

         191: Constant comparisons not supported
              Настоящая версия не позволяет сравнение констант (в разделе
              декларации)

         192: Constant routines not supported
              Настоящая версия не позволяет применение этой стандартной
              функции с константным параметром (в разделе декларации)

         193: Real constant expressions not supported
              Настоящая версия не позволяет применение выражений с участием
              реальных констант (в разделе декларации)

         194: Structure too long
              Размер структуры больше допустимого (64 Kbytes)

         195: Set base type out of range [0..255]
              Базовый тип множества вне интервала [0..255]

         211: Identifier is not of the appropriate class
              Идентификатор неправильного класса

         212: Undeclared Identifer
              Недекларированный идентификатор

         213: Unvisible Identifier
              Неразличимый идентификатор
                 Идентификатор определен в не менее двух модулях -
                 необходимо указать точно в каком из модулей будет
                 использован

         214: Illegal symbol (possibly missing ';' on line above)
              Неправильный символ (вероятно в предыдущей строке пропущен
              символ ";")

         215: Constant not allowed here
              Здесь не разрешено использование константы

         227: Constant out of range
              Недопустимое значение константы

         228: String constant exceeds source line
              Константа типа строки длиннее исходной строки

         229: String constant too long
              Константа типа строки длиннее 255 символов

         230: Procedure too long
              Недопустимо длинная процедура
                  Разделите ее на две части.

         70              UniPASCAL - Диагностические сообщения компилятора
         -----------------------------------------------------------------

         231: Too many (or too long) long constants
              Общая длина "длинных" констант больше 32 Kbytes
                 Совет - организуйте обработку одной из них в качестве
                 файла

         232: Too many procedures or functions
              Число процедур или функций больше 255.
                 Совет - обявить часть процедур с вложенными процедурами
                 сегментными или разделить программу на модули

         234: Too long segment
              Сенгмент длиннее допустимого
                 Совет - разделить его на два сегмента или модуля

         235: Too many segments
              Число сегментов больше 255
                 Совет - объединить некоторые из них. Если и это не
                 помагает, значить общее число процедур и функции больше
                 25000. Следует обдумать заново всю программу. В этом виде
                 ее нельзя выполнить на компьютере "Пылдин 601/601А".

         237: {$endif} expected
              Ожидается (но не найдена) директива {$endif}, закрывающая
              тело директивы типа {$IFxxx}

         238: Too many conditional symbols defined
              Обявлены более 8 символов условной компиляции

         239: Missplaced conditional directive
              Неправильное применение директивы условной компиляции






              11.3.  Фатальные ошибки


         240: Error in compiler include option
              Неправильная директива включения внешнего файла (include)

         241: Include files not allowed here
              Использование директивы включение файла здесь не разрешено
              (перед ключевого слова "program")

         242: Include files too nested
              Попытка осуществить больше 4 включений файлов

         243: Comment not closed
              Неоконченный комментарий

         244: Error in symbol table
              Ошибка в таблице символов
                 Совет - перекомпилировать соответствующий модуль

         UniPASCAL - Диагностические сообщения компилятора              71
         -----------------------------------------------------------------

         245: Error in date time of interface
              Ошибка в дате или времени связи
                 Вероятное всего некоторый модуль был перекомпилированным,
                 а использующие его модули - нет.

         246: Error reading symbol table
              Ошибка при вводе символьной таблицы
                 Вероятнее всего ошибка технического устройства -
                 перекомпилируйте модуль.

         247: Can't find symbol table
              Невозможно найти таблицу символов ( .sym файл)
                 Совет - перекомпилируйте модуль.

         248: Can't write code file
              Невозможно записать выходной (.pgm или .bdy или .sym) файл
                 Совет - проверьте есть ли на дискете свободного места.
                 Если да - технический сбой устройства.

         249: Can't open code file
              Невозможно открыть выходной (.pgm или .bdy или .sym) файл
                 Совет - проверьте есть ли на дискете свободного места.
                 Если да - технический сбой устройства.

         250: Include file not found
              Не найден файл для включения в исходный файл
                 Проверьте указали ли ПОЛНОЕ имя файла (с расширением и,
                 если необходимо, с логическим устройством, директории и
                 т.д.)

         252: Phisycal end of proc/func text encountared before logical
              Физический конец процедуры/функции найден перед логическим
              окончанием
                 Процедура или функция должна быть записана ПОЛНОСТЬЮ в
                 одном исходном/включаемом файле

         253: Can't read source file. (I/O error)
              Невозможно прочитать исходный файл (ошибка ввода/вывода)
                 Вероятнее всего - технический сбой.

         254: Source line too long
              Длина строки исходного файла больше 128 символов

         255: Phisycal end of program/unit text encountared before logical
              Физический конец программы/модуля найден перед логическим
              окончанием.

         72           UniPASCAL - Диагностические сообщения интерпретатора
         -----------------------------------------------------------------

              12.  Диагностические сообщения интерпретатора


           1: Insufficient room in memory
              Недостаточная свободная память (для выполнения программы)
                 Совет - разделите программу на перекрывающиеся модули.

           2: Input/Output error
              Ошибка ввода/вывода

           3: Division by zero
              Нулевое значение знаменателя

           4: String overflow
              Переполнение строки символов

           5: Element's number out of range
              Номер элемента множества вне интервала [0..255]

           6: Lo bound exceeds hi bound
              Нижная граница множества превышает верхную

           7: Bad string index
              Неправильное индексирование переменной типа строки

          65: Floating point overflow
              Переполнение при расчетах с плавающей точкой

          66: Invalid floating point operation
              Неправильная операция или операнд с плавающей точкой

          67: Floating point division by zero
              Нулевое значение знаменателя при делении с плавающей точкой

          68: Integer overflow
              Переполнение при превращении реального числа в целое

         209: Error reading code file
              Ошибка при вводе исполнимого файла
                 Вероятнее всего - технический сбой.

         210: Module not found
              Нет выполнимого кода указанного модуля

         211: Segment not found
              Не найден файл сегмента
                 Проверьте не поменяли ли дискету во время выполнения.

         212: Incorrect program version
              Неправильная версия программы/модуля

         UniPASCAL - Формальное описание языка                          73
         -----------------------------------------------------------------


                      ПРИЛОЖЕНИЕ 1 - Формальное описание языка


          ASCII_8 =           . ;any character of available character set

          Letter =            'A'| 'B'| 'C'| 'D'| 'E'| 'F'| 'G'| 'H'| 'I'|
                              'J'| 'K'| 'L'| 'M'| 'N'| 'O'| 'P'| 'Q'| 'R'|
                              'S'| 'T'| 'U'| 'V'| 'W'| 'X'| 'Y'| 'Z'| '_'|
                              'a'| 'b'| 'c'| 'd'| 'e'| 'f'| 'g'| 'h'| 'i'|
                              'j'| 'k'| 'l'| 'm'| 'n'| 'o'| 'p'| 'q'| 'r'|
                              's'| 't'| 'u'| 'v'| 'w'| 'x'| 'y'| 'z' .

          Digit =             '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'.

          Ident =             Letter { Letter | Digit | '_' }.

          HexDigit =          Digit | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' |
                                      'a' | 'b' | 'c' | 'd' | 'e' | 'f'.

          Decimal =           Digit { Digit | '_'}.

          IntConst =          Decimal | '$' HexDigit { HexDigit | '_'}.

          RealConst =         Decimal '.' Decimal ['E' ['+'|'-'] Decimal].

          CharConst =         '"' ASCII_8 '"' |
                              "'" ASCII_8 "'" |
                              '#' IntConst.

          StringConst =       { '"' { ASCII_8 } '"' |
                                "'" { ASCII_8 } "'" |
                                '#' IntConst          } |
                                "''" | '""' .

          Comment =           '{'  { ASCII_8 }  '}' |
                              '(*' { ASCII_8 } '*)'.

          Program =           ProgramHeading
                              [ UsesClause ]
                              Block "."      .

          UsesClause =        { 'uses' IdentList ';' }.

          IdentList =         Ident { ',' Ident }.

          ProgramHeading =    'program' Ident ['('ExternalFiles')' ] ';'.

          ExternalFiles =     IdentList.

          Block =             [Declarations]
                              'begin'
                                Statement { ';'
                                Statement }
                              'end'.

         74                          UniPASCAL - Формальное описание языка
         -----------------------------------------------------------------


          Declarations =      { LabelDecl |
                                ConstDecl |
                                TypeDecl  |
                                VarDecl   |
                                PFDecl    } .

          Label =             (Ident | IntConst).

          LabelDecl =         'label' Label { ',' Label } ';'.

          ConstDecl =         'const' Ident '=' ConstExpr ';'
                                    { Ident '=' ConstExpr ';' }.

          ConstExpr =         Expression.

          TypeDecl =          'type' Ident '=' Type ';'
                                   { Ident '=' Type ';' }.

          Type =              (SimpleType     |
                               PointerType    |
                               StructuredType |
                               StringType     ).

          SimpleType =        Ident | OrdinalType | Real.

          VarDecl =           'var' IdentList ':' Type ';'
                                  { IdentList ':' Type ';' }.

          PFDecl =            { ProcDecl } | { FuncDecl }.

          Enumerated =        '(' IdentList ')'.

          SubRange =          OrdinalConstant '..' OrdinalConstant.

          StructuredType=     ['packed']
                                (ArrayType  |
                                 RecordType |
                                 SetType    |
                                 FileType   ).

          ArrayType =         'array' '[' IndexType { ',' IndexType } ']'
                                                               'of' Type.

          IndexType =         SubRange | Enumerated | Char | Boolean.

          StringType =        string '[' ShortCard ']'.

          RecordType =        'record' FieldList 'end'.

          FieldList =         FixedPart [';'] |
                              VariantPart [';'] |
                              FixedPart ';' VariantPart [';'].

          FixedPart =         FieldIdent { ',' FieldIdent } ':' Type {';'
                              FieldIdent { ',' FieldIdent } ':' Type     }.

         UniPASCAL - Формальное описание языка                          75
         -----------------------------------------------------------------

          VariantPart =       'case' TagField 'of'
                                OrdinalConstList ':' '(' FieldList ')' {';'
                                OrdinalConstList ':' '(' FieldList ')'   }.

          FieldIdent =        Ident.

          TagField =          [TagIdent ':'] TagFieldType.

          TagFieldType =      OrdinalType.

          TagIdent =          Ident.

          OrdinalType =       IntType    |
                              Enumerated |
                              SubRange   |
                              Boolean    |
                              Char       .

          IntType =           Integer  |
                              ShortInt |
                              LongInt  |
                              Cardinal |
                              Natural  |
                              ShortCard.

          SetType =           'set' 'of' OrdinalType.

          SetConstructor =    '[' [ SetItem { ',' SetItem } ] ']'.

          SetItem =           ConstExpr { '..' ConstExpr }.

          FileType =          'file' ['of' Type].

          PointerType =       '^' BaseType .

          BaseType =          Type .

          Statement =         [ LabelRef ':' ] ( SimpleStatement |
                                StructuredStatement ) .

          LabelRef =          Ident | Decimal .

          SimpleStatement =   EmptyStatement     |
                              Assignment         |
                              ProcedureStatement |
                              GotoStatement .

          EmptyStatement =    .

          Assignment =        ( VariableIdent |
                              FuncIdent ) ':=' Expression .

          GotoStatement =     "goto" LabelRef .

          ProcedureStatement= [ UnitIdent '.']
                                ProcIdent [ ActualParameterList ] .

         76                          UniPASCAL - Формальное описание языка
         -----------------------------------------------------------------


          ProcDecl =          ProcHeading ';' (ProcBody | Directive) ';' .

          ProcHeading =       [ 'segment' ]
                                'procedure' ProcIdent [FormalParamsList] .

          ProcIdent =         Ident.

          Directive =         'forward' | 'external' .

          ProcBody =          Block .

          StructuredStatement=CompoundStatement    |
                              ConditionalStatement |
                              RepetitiveStatement  |
                              WithStatement .

          StatementList =     Statement { ';' Statement } .

          CompoundStatement=  'begin' StatementList 'end' .

          ConditionalStatement=IfStatement | CaseStatement .

          IfStatement =       'if' Expression
                                'then' Statement
                              [ 'else' Statement ] .

          CaseStatement =     'case' TagExpr 'of'
                                 OrdinalConstList ':' Statement {';'
                                 OrdinalConstList ':' Statement }
                              [ 'else' ':' Statement ]
                              'end'.

          TagExpr =           Expression.

          OrdinalConstList =  OrdinalConst { ',' OrdinalConst } .

          OrdinalConst =      IntConst |
                              CharConst |
                              BoolConst .

          BoolConst =         ( TRUE | FALSE) .

          FuncDecl =          FuncHeading ';'( FuncBody | Directive ) ';' .

          FuncHeading =       [ 'segment' ] 'function' FuncIdent
                              [ FormalParamsList ]':' ResultType .

          FuncIdent =         Ident.

          ResultType =        SimpleType | Pointer .

          FuncBody =          Block .

          FormalParamsList =  '(' ParamDecl { ',' ParamDecl } ')' .

         UniPASCAL - Формальное описание языка                          77
         -----------------------------------------------------------------

          ParamDecl =         [ 'var' ] IdentList ':' TypeIdent |
                                'var'   IdentList  .

          TypeIdent =         Ident.

          VariableIdent =     Ident.

          ActualParameterList='(' ActualParam { ',' ActualParam } ')' .

          ActualParam =       Expression | VariableRef .

          RepetitiveStatement=WhileStatement  |
                              RepeatStatement |
                              ForStatement    .

          WhileStatement=     'while' BooleanExpr 'do'
                                 Statement .

          RepeatStatement =   'repeat' StatementList
                              'until'  BooleanExpr .

          BooleanExpr =       Expression.

          ForStatement =      'for' ControlVariable ':=' InitialValue
                              ( 'to' | 'downto' ) FinalValue 'do'
                                 Statement .

          WithStatement =     'with' IdentList 'do'
                                Statement.

          ControlVariable =   LocalVariableIdent .

          LocalVariableIdent=Ident .

          InitialValue=       Expression .

          FinalValue=         Expression .

          Expression =        SimpleExpression
                              [ relation SimpleExpression ] .

          SimpleExpression =  [ '+' | '-' ] Term { AddOperator Term } .

          Term =              Factor { MullOperator Factor } .

          Factor =            ConstantRef |
                              VariableRef |
                              SetConstructor |
                              FunctionCall |
                              'not' Factor |
                              '(' Expression ')' .

          relation =          '=' | '<>' | '<' | '<=' | '>=' | '>' | 'in' .

          AddOperator  =      '+' | '-' | 'or' | 'xor' | '|' .

         78                          UniPASCAL - Формальное описание языка
         -----------------------------------------------------------------


          MullOperator =      '*' | '/' | 'div' | 'mod' | 'and' | '&' .

          Constant =          OrdinalConst
                              RealConst
                              StringConst .

          ConstantRef =       Constant | ConstIdent | 'nil' .

          ConstIdent =        Ident.

          VariableRef =       Ident.

          FunctionCall =      [ UnitIdent '.' ] FuncIdent
                              [ '(' ActualParam { ',' ActualParam } ] .

          Unit =              'unit' UnitIdent ';'
                                InterfacePart
                                ImplementationPart .

          UnitIdent =         Ident.

          InterfacePart =     'interface'
                                [ UsesClause ]
                              InterfaceDecl .

          InterfaceDecl =     { ConstDecl | TypeDecl | VarDecl | PFDecl }.

          ImplementationPart= 'implementation'
                                  [ UsesClause ]
                                (( Declarations 'end') |
                                 Block |
                                 'end') .

          Compilation =       ( Program            |
                                Unit               |
                                InterfaceUnit      |
                                ImplementationUnit ) '.'.

          InterfaceUnit =     'interface' 'unit' Ident ';'
                                [ UsesClause ]
                                InterfaceDecl
                              'end'.

          ImplementationUnit= 'implementation' 'unit' Ident ';'
                                [ UsesClause ]
                              Block.

          TRUE =              Ident.

          FALSE =             Ident.

          Integer =           Ident.

          Cardinal =          Ident.

         UniPASCAL - Формальное описание языка                          79
         -----------------------------------------------------------------

          Natural =           Ident.

          ShortInt =          Ident.

          LongInt =           Ident.

          ShortCard =         Ident.

          Boolean =           Ident.

          Char =              Ident.

          Real =              Ident.

          Pointer =           Ident.

          string =            Ident.

         80                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------

              ПРИЛОЖЕНИЕ 2 - Стандартые процедуры и функции UniPascal

         function ABS
         ------------
              Предназначение: Расчет абсолютного значения выражения
              Декларация: function Abs(x)
              Результат: Того-же типа что и параметр
              Действие:  x - арифметическое выражение целого (integer) или
                         реального (real) типа.  Результат - абсолютное
                         значение выражения.
              Пример:     program ExampleABS;
                          begin
                          writeln('abs(-12) = ', abs(-12),
                                ', abs(-1.5) = ', abs(-1.5));
                          end.

         function ADDR
         -------------
              Предназначение: Получение адреса переменной.
              Декларация: function Addr(var x): pointer;
              Результат: Типа указателя (pointer).
              Действие:  x - переменная.  Результат указатель, направленный
                         на х.  Как и константа nil, резултат функции Addr
                         совместим со всеми указателями.
              Пример:     program ExampleADDR;
                            var p: pointer; i: integer;
                          begin
                          p:= Addr(i); { p указывает на i }
                          end.


         function ArcTan
         ---------------
              Предназначение: Расчет аркус тангеса от x.
              Декларация:  function ArcTan(x:  real):  real;
              Действие:  x - арифметическое выражение реального типа.
                         Результат (в радианах) - аркус тангес x .


         procedure BlockRead
         -------------------
              Предназначение: Считывание с файла определенного числа
                              байтов.
              Декларация:  procedure BlockRead(var f:  file; var Buffer;
                           count:  Cardinal [; var Result:  Cardinal]);
              Действие:  При выполнении BlockRead считываются count (или
                         меньше) байтов с файла f в паметь компьютера,
                         начибая с первого байта, занимаемого Buffer-ом.
                         Число действительно считанных байтов становится
                         значением параметра Result (если задан).  Если не
                         задан параметр Result и было считано меньшее
                         заданного число байтов, выводится сообщение об
                         ошибке ввода/вывода (I/O error).
                         Если введена директива {$I-} то программист должен
                         сам позаботиться об обработке ошибки.
              Смотрите также и:  BlockWrite.

         UniPASCAL - Стандартные процедуры и функции                    81
         -----------------------------------------------------------------

         procedure BlockWrite
         --------------------
              Предназначение: Запись в файл определенного числа байтов.
              Декларация:  procedure BlockWrite(var f:  file; const Buffer;
                           count: Cardinal [; var  Result: Cardinal]);
              Действие:  При выполнении BlockWrite записываются count (или
                         меньше) байтов с памяти (начиная с первого байта,
                         занимаемого Buffer-ом) в файл f.
                         Число действительно записанных байтов становится
                         значением параметра Result (если задан).  Если не
                         задан параметр Result и было записано меньше
                         заданного число байтов, выводится сообщение об
                         ошибке ввода/вывода (I/O error). Если введена
                         директива {$I-} то программист должен сам
                         позаботиться об обработке ошибки.
              Смотрите также и:  BlockRead.


         function CHR
         ------------
              Предназначение: Генерация символа с заданным ASCII-кодом
              Декларация:  function Chr(x:  ShortCard):  char;
              Результат: типа char.
              Действие:  x - целочисленное арифметическое выражение.
                         Результат - символ с ASCII-кодом = x.
              Смотрите также и:  ORD
              Пример:     program ExampleCHR;
                            var digit: 0..9;
                          begin { вывод цифр от 0 до 9 }
                          for d:= 0 to 9 do
                            write(chr(ord('0') + digit));
                          end.


         procedure CLOSE
         ---------------
              Предназначение:  Закрытие файла.
              Декларация:  procedure Close(f);
              Действие:  f - переменная типа файл, связанная с типизиро-
                         ванным или нетипизированным файлом.  Если файл
                         открыт оператором reser, rewrite или open то
                         проводятся все необходимые действия для закрытия
                         файла, после чего прерывается связь между
                         переменной и файлом.
              Смотрите также и:  RESET, REWRITE, OPEN



         function COS
         ------------
              Предназначение:  Расчет косинуса.
              Декларация:  function COS(x:  real):  real;
              Действие:  Расчет косинуса от заданного в радианах параметра.
              Смотрите также и:  SIN, ArcTan

         82                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------

         procedure DEC
         -------------
              Предназначение:  Уменьшение значения переменной.  Декларация:
         procedure Dec(var x [, n]); Действие:  x - переменная простого
         типа; n - необязательное арифметическое выражение.  При выполнении
         процедуры переменной х присваивается значение, равное старому за
         вычетом n, если n задано, или 1, если n не задано.
              Пример:     program ExampleDEC;
                            var i: integer; l: LongInt;
                          begin
                          Dec(i, 3);  { i:= i - 3; }
                          Dec(l);     { l:= l -1; }
                          end.


         procedure DELETE
         ----------------
              Предназначение: Удаление подстроки из строки.
              Декларация:  procedure Delete(var s:string; ndx,
                           count:ShortCard);
              Действие:  Удаление из строки s count-символов, начиная с
                         позиции ndx.
              Смотрите также и:  INSERT, POS




         procedure DISPOSE
         -----------------
              Предназначение:  Удаление динамической переменной.
              Декларация:  procedure Dispose(p [, CaseValue, ...]);
              Действие:  p - переменная типа указателя, указывающая на ди-
                         намическую переменную.  При выполнении процедуры
                         указываемая динамическая переменная удаляется и
                         занимаемая ею память становится доступной для
                         дальнейшего применения.

              Ограничение:  Вариантные константы должны быть те-же самые,
                            что и при занятии памяти процедурой NEW.
              Смотрите также и:  FreeMemWords, GetMemWords, New, Mark,
                                 Release



         function EOF
         ------------
              Предназначение:  Проверка на достижение конца файла.
              Декларация:  function EOF [(f)]:  boolean;
              Действие:  f - переменная типа файла.  Если f не задано
                         подразумевается стандартный входной файл.
                         Результат TRUE, если позиционирование в файле
                         после последней записи и FALSE в противном случае.
              Смотрите также и:  EOLN

         UniPASCAL - Стандартные процедуры и функции                    83
         -----------------------------------------------------------------

         function EOLN
         -------------
              Предназначение:  Проверка на достижение конца строки.
              Декларация:  function EOLN [(f)]:  boolean;
              Действие:  f - переменная типа текстового файла.  Если f не
                         задано подразумевается стандартный входной файл.
                         Результат TRUE, если позиционирование в файле
                         после последнего символа строки - т.е.  на маркер
                         EOLN, или после последней записи - т.е.
                         EOF(f)=TRUE, и FALSE в противном случае.
              Смотрите также и:  EOF


         function EXP
         ------------
              Предназначение:  Расчет экспоненты.
              Декларация:  function Exp(x:  real):  real;
              Действие:  x - арифметическое выражение реального типа.
                         Результат - экспонента x.



         function FilePos
         ----------------
              Предназначение:  Получение текущей позиции в файле.
              Декларация:  function FilePos(f):  LongInt;
              Действие:  f - файловая переменная.  Результат типа LongInt.
                         Если текущая позиция соответствует началу файла то
                         FilePos равно  0, а если соответствует концу
                         файла (EOF(f)=true) то FilePos(f) = FileSize(f).
              Ограничения:  Файл должен быть нетекстовым и открытым.
              Смотрите также и:  FileSize, Seek




         function FileSize
         -----------------
              Предназначение:  Получение размера (длины) файла.
              Декларация:  function FileSize(f):  LongInt;
              Действие:  f - файловая переменная.  Результат типа LongInt.
                         Результат - число компонентов файла.
              Ограничения:  Файл должен быть нетекстовым и открытым.
              Смотрите также и:  FilePos




         procedure FillChar
         ------------------
              Предназначение:  Заполнение непрерывной област памяти.
              Декларация:  procedure FillChar(var Src; count:Natural;
                           ch:char);
              Действие: непрерывная область памяти с начальным адресом Src
                        заполняется символом ch, повторенным count раз.

         84                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------


         procedure FillWord
         ------------------
              Предназначение:  Заполнение непрерывной област памяти.
              Декларация:  procedure FillWord(var Src; count:  Natural;
                           W:word);
              Действие: непрерывная область памяти с начальным адресом Src
                        заполняется словом W, повторенным count раз.






         function FRAC
         -------------
              Предназначение:  Получение дробной части реального числа.
              Декларация:  function FRAC(x:  real):  real;
              Действие: возврат в качестве результата реального типа
                        дробной части реального арифметического выражения
                        x, заданного в качестве параметра.





         procedure FreeMemWords
         ----------------------
              Предназначение:  Освобождение занятой памяти.
              Декларация:  procedure FreeMemWords(p:  pointer;
                           WrdSz: Natural);
              Действие:  p - переменная типа указателя, указывающая на ди-
                         намическую переменную длиной в WrdSz слов.  При
                         выполнении процедуры указываемая динамическая
                         переменная удаляется и занимаемая ею память
                         становится доступной для дальнейшего применения.
              Смотрите также и:  Dispose, GetMemWords, New, Mark, Release






         procedure GetDate
         -----------------
              Предназначение:  Получение текущей даты.
              Декларация:  procedure GetDate(var Year, Month, Day:  word);
              Действие:  Переменным Year, Month, Day присваиваются значения
                         текущего года, месяца и дня, соответственно.  Year
                         может быть от 1980 до 2099, Month - от 1 до 12, а
                         Day - от 1 до 31.
              Смотрите также и:  GetTime

         UniPASCAL - Стандартные процедуры и функции                    85
         -----------------------------------------------------------------

         procedure GetMemWords
         ---------------------
              Предназначение:  Занятие памяти.
              Декларация:  procedure GetMemWords(var p:pointer;
                           WrdSz: Natural);
              Действие:  p - переменнная типа указателя. В памяти
                         занимается область размером в WrdSz слов. Начало
                         области возвращается в р.
              Внимание!  Нельзя рассчитывать что память, занятая двумя
                         последовательными выполнениями процедуры, образует
                         непрерывное поле памяти.
              Смотрите также и:  Dispose, GetMemWords, New, Mark, Release




         procedure GetTime
         -----------------
              Предназначение:  Получение текущего времени.
              Декларация:  procedure GetTime(var Hour,Min,Sec,s100: word);
              Действие:  Переменным Hour,Min,Sec и s100 присваиваются зна-
                         чения текущего часа, минуты, секунды и сотой се-
                         кунды, соответственно.  Hour может быть от 0 до
                         23, Min и Sec - от 0 до 59, а s100 - от 0 до 99.
              Смотрите также и:  GetDate




         procedure HALT
         --------------
              Предназначение:  Прекращение выполнения программы.
              Декларация:  procedure Halt [(ExitCode:  Natural)];
              Действие:  ExitCode - необязательный параметр и, если не
                         указан, подразумевается 0. Выполнение программы
                         прекращается.



         function Hi
         -----------
              Предназначение:  Получение старшего байта слова.
              Декларация:  function Hi(x:  word):  byte;
              Действие:  x - арифметическое выражение с размером в 1 слово.
                         Результат типа byte и представляет собой старший
                         байт параметра.


         function HiWord
         ---------------
              Предназначение:  Получение старшего слова двойного слова.
              Декларация:  function HiWord(x:  LongWord):  word;
              Действие:  x - арифметическое выражение с размером в 1
                         двойное слово. Результат типа word и представляет
                         собой старшee слово параметра.

         86                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------

         procedure INC
         -------------
              Предназначение: Увеличение значения переменной.
              Декларация:  procedure Inc(var x [, n]);
              Действие:  x - переменная простого типа; n - необязательное
                         арифметическое выражение.  При выполнении проце-
                         дуры переменной х присваивается значение, равное
                         старому, увеличенное на n, если n задано, или на
                         1, если n не задано.




         procedure Insert
         ----------------
              Предназначение:  Вставка строки в другую строку.
              Декларация:  procedure Insert(const Src:  string;
                           var s: string; index:  ShortCard);
              Действие:  Строка Src вставляется в строку s начиная с
                         позиции index.




         function INT
         ------------
              Предназначение:  Получение целой части реального числа.
              Декларация:  function INT(x:  real):  real;
              Действие: возврат в качестве результата реального типа
                        целой части реального арифметического выражения
                        x, заданного в качестве параметра.




         function IOresult
         -----------------
              Предназначение:  Получение кода ошибки при последнем
                               выполнении операции ввода/вывода.
              Декларация:  function IOresult:  integer;
              Действие: Результатом функции является код завершения
                        операции ввода/вывода. Код = 0 - операция
                        осуществлена успешно.
              Внимание! До выполнения функции должна быть выполнена
                        директива {$I-}.


         function LENGTH
         ---------------
              Предназначение:  Получение длины строки.
              Декларация:  function length(const s:  string):  ShortCard;
              Действие:  Результатом функции является длина заданной в
                         качестве параметра строки.

         UniPASCAL - Стандартные процедуры и функции                    87
         -----------------------------------------------------------------

         function Ln
         -----------
              Предназначение:  Расчет натурального логарифма.
              Декларация:  function Ln(x:  real):  real;
              Действие:  x - арифметическое выражение реального типа.
                         Результат - натуральный логарифм x.


         function Lo
         -----------
              Предназначение:  Получение младшего байта слова.
              Декларация:  function Lo(x:  word):  byte;
              Действие:  x - арифметическое выражение с размером в 1 слово.
                         Результат типа byte и представляет собой младший
                         байт параметра.



         function LongSwap
         -----------------
              Предназначение:  Обмен значениями байтов двойного слова.
              Декларация:  function LongSwap(w:  LongWord):  LongWord;
              Действие:  В двойном слове попарно обмениваются значениями
                         байты по схеме 1 <-> 4, 2 <-> 3.
              Смотрите также и:  Lo, LoWord, Hi, HiWord, Swap



         function LoWord
         ---------------
              Предназначение:  Получение младшего слова двойного слова.
              Декларация:  function LoWord(x: LongWord):  word;
              Действие:  x - арифметическое выражение с размером в 1
                         двойное слово. Результат типа word и представляет
                         собой младшee слово параметра.
              Смотрите также и:  Lo, Hi, HiWord, Swap, LongSwap



         procedure MARK
         --------------
              Предназначение:  Пометка состояния динамической памяти.
              Декларация:  procedure Mark(var p:  pointer);
              Действие:  При выполнении процедуры в переменной типа
                         указателя р помечается состояние динамической
                         памяти (адрес первого свободного байта).
                         Переменная р дальше следует использовать в
                         качестве параметра процедуры RELEASE для удаления
                         всех динамических переменных, созданных после
                         пометки.  Переменная р не должна изменяться после
                         вызова процедуры MARK вплоть до выполнения
                         процедуры RELEASE.
              Смотрите также и:  New, Dispose, GetMemWords, FreeMemWords,
                                 Release

         88                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------


         function MaxAvail
         -----------------
              Предназначение:  Получение объема наибольшего непрерывного
                               блока свободной памяти.
              Декларация:  function MaxAvail:  Natural;
              Действие:  Результат процедуры - объем в словах наибольшего
                         непрерывного блока свободной памяти.
              Смотрите также и:  MemAvail




         function MemAvail
         -----------------
              Предназначение:  Получение полного объема свободной памяти.
              Декларация:  function MemAvail:  Natural;
              Действие:  Результат процедуры - объем в словах всех блоков
                         свободной памяти - т.е.  полный объем свободной
                         памяти.
              Смотрите также и:  MaxAvail



         procedure Move
         --------------
              Предназначение:  Перемещение непрерывной области памяти.
              Декларация:  function Move(const Src; var Dest;
                           Nbytes: Cardinal);
              Действие:  Начиная с адреса Src, Nbytes байтов перемещаются в
                         переменную Dest.


         procedure MoveWords
         -------------------
              Предназначение:  Перемещение непрерывной области памяти.
              Декларация:  function MoveWords(const Src; var Dest;
                           Nwords: Cardinal);
              Действие:  Начиная с адреса Src, Nwords слов перемещаются в
                         переменную Dest.




         procedure NEW
         -------------
              Предназначение:  Создание новой динамической переменной.
              Декларация:  procedure NEW(var p [, CaseValue, ...]);
              Действие:  Создается новая динамическая переменная и ее адрес
                         заносится в переменной типа указателя p.
                         Вариантные константы должны следовать в порядке
                         нарастания вложенности вариантных частей.
              Смотрите также и:  Dispose, FreeMemWords, GetMemWords, Mark,
                                 Release

         UniPASCAL - Стандартные процедуры и функции                    89
         -----------------------------------------------------------------

         function Odd
         ------------
              Предназначение:  Проверка на нечетность.
              Декларация:  function Odd(x:  integer):  boolean;
              Действие:  Результат TRUE, если параметр нечетное число.



         procedure OPEN
         --------------
              Предназначение:  Открытие файла для ввода/вывода.
              Декларация:  procedure OPEN(f; Fname:  string);
              Действие:  Открытие внешнего файла с именем, заданном в
                         переменной Fname.  Если файл с таким именем не
                         существует, то он создается и открывается.
              Смотрите также и:  Close, Reset, Rewrite



         function ORD
         ------------
              Предназначение:  Получение очередного номера в множестве
                               значении заданного типа.
              Декларация:  function Ord(x):  integer;
              Действие:  x - параметр простого типа.  Функция возвращает
                         номер x в множестве значении типа, которому
                         принадлежит.



         function ParamCount
         -------------------
              Предназначение: Счет числа параметров, введенных с командной
                              строки.
              Декларация:  function ParamCount:  Natural;
              Действие:  Возвращает число параметров, введенных с командной
                         строки операционной системы в момент запуска
                         программы. Если программа вызвана без параметров,
                         результат функции - 0.
              Смотрите также и:  ParamStr


         procedure ParamStr
         ------------------
              Предназначение:  Получение значения параметра, введенного с
                               командной строки.
              Декларация:  procedure ParamStr(N:  Natural; var s:  string);
              Действие:  Получение в строку S значения N-ого по очереди
                         введенного с командной строки операционной системы
                         параметра.  Если N = 0 то получается имя
                         программы.

         90                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------


         function POS
         ------------
              Предназначение:  Поиск в строке подстроки.
              Декларация:  function POS(const SubStr, Src:  string):
                           ShortCard;
              Действие:  В строке Src осуществляется поиск строки SubStr и,
                         если найдена, возвращается номер позиции с которой
                         начинается. Если в Src не содержится SubStr, то
                         результатом является 0.




         function PRED
         -------------
              Предназначение:  Получение предыдущего элемента множества
                               значении заданного типа.
              Декларация:  function Pred(x)
              Действие:  x - выражение простого типа.  Результат функции
                         того-же типа и является предыдущим по очереди
                         элемента множества значении типа.





         function Random
         ---------------
              Предназначение:  Получение псевдо-случайного числа.
              Декларация:  function Random [ (x:  Cardinal) ]
              Действие:  Если не задан параметр результат реальное число
                         в интервале 0 <= Random < 1.  Если задан параметр,
                         то результат целое число в интервале 0 <=
                         Random(x) < x
              Смотрите также и:  Randomize




         procedure Randomize
         -------------------
              Предназначение:  Инициализация генератора случайни чисел.
              Декларация:  procedure Randomize[(c: cardinal)];
              Действие:  Если эта процедура не была выполненной, программа
                         при каждом вызове процедуры RANDOM будет получать
                         очередное число постоянного ряда случайных чисел.
                         В некоторых случаях это необходимо.  Что бы
                         инициализировать новый ряд псевдослучайных чисел,
                         необходимо выполнить RANDOMIZE без параметров.
                         Если задан параметр, первым числом ряда чисел
                         будет параметр.

         UniPASCAL - Стандартные процедуры и функции                    91
         -----------------------------------------------------------------


         procedure READ
         --------------
              Предназначение:  Ввод с типизированного файла.
              Декларация:  procedure Read([f,] v1 [, v2, ...  vn]);
              Действие:  f - файловая переменная.  Если она не задана,
                        используется стандартный входной файл.  Если f -
                        текстовый файл (или не задано) v1,..., vn должны
                        быть переменными типа integer, cardinal, longint,
                        char или ихные диапазоны, а так-же real или
                        string.  С файла считываются символы преобразуются
                        во внутренные формы представления соответствующего
                        типа.  Если f - типизированный файл, то v1, ..., vn
                        должны быть типа компонент этого файла.  Для каждо-
                        го v считывается необходимое количество байтов.



         procedure ReadLn
         ----------------
              Предназначение:  Ввод с файла с последующим пропуском
                               символов до конца строки (записи).
              Декларация:  procedure Readln([f ,] [v1, ..., vn]);
              Действие:  Процедура применима только для текстового файла.
                         Она эквивалентна по действию процедуре Read с теми
                         самыми параметрами.  После ввода последнего
                         заданного параметра, символы до конца строки
                         файла пропускаются и подготавливается ввод
                         следующей строки.


         procedure Release
         -----------------
              Предназначение:  Восстановление состояния динамической памяти.
              Декларация:  procedure Release(p:  pointer);
              Действие:  Динамическая память, занятая после вызова
                         процедуры MARK освобождается и соответствующие
                         динамические переменные удаляются.
              Смотрите также и:  Dispose, FreeMemWords, GetMemWords, New,
                                 Mark


         procedure RESET
         ---------------
              Предназначение:  Открытие файла для ввода.
              Декларация:  procedure RESET(f; Fname:  string);
              Действие:  Открытие только для ввода внешнего файла с именем
                         в переменной Fname.  Попытка вывода в файл
                         приводит к ошибке ввода/вывода.
              Смотрите также и:  Close, Open, Rewrite

         92                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------

         procedure REWRITE
         -----------------
              Предназначение:  Создание нового внешнего файла.
              Декларация:  procedure REWRITE(f; Fname:  string);
              Действие:  Создание нового внешнего файла с именем в
                         переменной Fname.  Попытка ввода с файла приводит
                         к ошибке ввода/вывода.
              Смотрите также и:  Close, Reset, Open


         function Round
         --------------
              Предназначение:  Превращение реального числа в целое путем
                               округления.
              Декларация:  function Round(x:  real):  LongInt;
              Действие:  Значение арифметического выражения реального типа
                         округляется и получает тип целого числа.


         procedure Seek
         --------------
              Предназначение:  Изменение позиции файла.
              Декларация:  procedure Seek(f; NewPos:  LongInt);
              Действие:  Указатель позиции файла получает значение NewPos.
                         Первый элемент файла имеет номер позиции 0.  Если
                         NewPos больше FileSize(f) и файл открыт процедурой
                         RESET (т.е.  только для ввода) то возникает ошибка
                         ввода/вывода.  Если файл открыт и для вывода, то
                         его длина увеличивается.
              Ограничения: Процедура не работает с текстовыми файлами.

         function SIN
         ------------
              Предназначение:  Расчет синуса.
              Декларация:  function SIN(x:  real):  real;
              Действие:  Расчет синуса заданного в радианах параметра.
              Смотрите также и:  COS, ArcTan


         function SizeOf
         ---------------
              Предназначение: Расчет в байтах длины параметра.
              Декларация:  function SizeOf(x [CaseValue, ...]):  Cardinal;
              Действие:  x может быть переменной или типом.  Если тип с
                       вариантными записями (или переменная этого типа) то
                       возможно перечислить вариантные константы таким-же
                       способом, как и в NEW и DISPOSE.


         function SQR
         ------------
              Предназначение:  Расчет квадрата значения параметра.
              Декларация:  function SQR(x)
              Действие:  x - арифметическое выражение целого или реального
                         типа.  Результат функции того-же типа.

         UniPASCAL - Стандартные процедуры и функции                    93
         -----------------------------------------------------------------



         function SQRT
         -------------
              Предназначение:  Расчет квадратного корня.
              Декларация:  function SQRT(x:  real):  real;
              Действие:  Результат функции - квадратный корень значения
                         параметра.



         function Succ
         -------------
              Предназначение:  Получение следующего элемента множества
                               значении заданого типа.
              Декларация:  function Succ(x)
              Действие:  x - выражение простого типа.  Результат того-же
                         типа и представляет собой следующий после
                         параметра элемент множества типа.



         function Swap
         -------------
              Предназначение: Обмен значениями младшего и старшего байта
                              одного слова.
              Декларация:  function Swap(w:  word):  word;
              Действие:  Старший и младший байт одного слова обмениваются
                         значениями.
              Смотрите также и:  LoWord, Hi, HiWord, Swap, LongSwap


         function TRUNC
         --------------
              Предназначение:  Превращение реального числа в целое число
                               путем удаления дробной части.
              Декларация:  function trunc(r:  real):  LongInt;
              Действие:  trunc(r) = round(int(r));




         function WordSizeOf
         -------------------
              Предназначение: Расчет длины в словах параметра.
              Декларация:  function WordSizeOf(x [CaseValue, ...]):
                           Cardinal;
              Действие:  x может быть переменной или типом.  Если тип с
                       вариантными записями (или переменная этого типа) то
                       возможно перечислить вариантные константы таким-же
                       способом, как и в NEW и DISPOSE.

         94                    UniPASCAL - Стандартные процедуры и функции
         -----------------------------------------------------------------


         procedure Write
         ---------------
              Предназначение:  Вывод в типизированный файл.
              Декларация:  procedure Write([f,] v1 [, v2, ...  vn]);
              Действие:  f - файловая переменная.  Если она не задана,
                        используется стандартный выходной файл.  Если f -
                        текстовый файл (или не задано) v1,..., vn должны
                        быть переменными типа integer, cardinal, longint,
                        char или ихные диапазоны, а так-же real или string.
                        Переменные преобразуются с внутренных форм в
                        символы и тогда выводятся.  Если f - типизированный
                        файл, то v1, ..., vn должны быть типа компонент
                        этого файла.


         procedure WriteLn
         -----------------
              Предназначение:  Вывод в файл с последующим переходом на
                               новую строку.
              Декларация:  procedure WriteLn([f ,] [v1, ..., vn]);
              Действие:  Процедура применима только для текстового файла.
                         Она эквивалентна по действию процедуре Write с
                         теми самыми параметрами.  После вывода последнего
                         заданного параметра осуществляется переход на
                         новую строку.