Ярославский Государственный Университет им. П.Г. Демидова
Опубликован: 06.11.2008 | Доступ: свободный | Студентов: 988 / 62 | Оценка: 4.50 / 4.00 | Длительность: 10:47:00
Лекция 3:

Язык РЕФАЛ: сложные конструкции Рефала-2

< Лекция 2 || Лекция 3 || Лекция 4 >
Аннотация: Спецификации переменных: синтаксис спецификации; спецификатор и его элементы; элементы-множества спецификатора; общий вид спецификатора; определение имени спецификатора и его использование. Структора рефал-программы и ее модулей: директива программы и ее части; директива комментария; ключевые слова директив; модульность и объявление входов и внешних имен; пример двухмодульной программы.
Ключевые слова: переменная, рефал-предложение, описание переменной, тип переменной, спецификатор, цепочка символов, описание некоторого множества термов, элементы, конечные, множества, терм, литеры, цепочка элементов спецификатора, функция, identical, выражение, значение, Рефал, ABC, имя спецификатора, арифметическая операция, separate, идентификатор, Структурные скобки, отождествление справа налево, Рефал-программа, модуль программы, комментарий, директива, части директивы, пробел, директива описания функции, информация, Директива рефал-предложени, Директива спецификатора, идентификатор спецификатора, ключевое слово, информация директивы, пустая директива, Ключевые слова директив, Entry, EXTRN, внешняя функция, отождествление, модуль, программа, ассемблер, Имена входов, идентификатор внешней функции, имя, имя внутренней функции, имя внешней функции

Спецификации переменных

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

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

  • S - множество всех символов;
  • B - множество структурных термов;
  • W - множество всех термов;
  • F - множество символов-меток;
  • N - множество символов-чисел;
  • R - множество символов-ссылок;
  • O - множество символов-литер (знаков символов);
  • L - множество прописных букв (латинских и русских);
  • D - множество десятичных цифр.

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

Ident    S(L)1 E(LD)2 = 'T'
               Ex = 'F'

Функция Ident при интерпретации первого рефал-предложения проверяет, является ли первый символ выражения аргумента буквой (для этого первый выделяемый символ S1 имеет спецификацию L) и являются ли все последующие символы, если они есть (переменная типа E может интерпретировать пустое значение), буквами или цифрами. Если это так, то возвращается символ 'T'. А если это не так, то второе рефал-предложение (всегда выполнимое) возвратит символ 'F', что и требовалось.

В общем случае спецификатор имеет вид:

P1(Q1)... Pn(Qn)P0,

где P_{i} (i\in \overline {0,n}),\setminus  Q_{i} (i\in \overline {1,n}) - произвольные цепочки элементов спецификатора (возможно, пустые). Если P0 - пустая цепочка, то считается P0=W (множеству всех термов). Наличие цепочки элементов спецификатора в круглых скобках означает, что элементы множества этой цепочки удаляются, а цепочка без круглых скобок ведет к добавлению в суммарное множество элементов множества этой цепочки. Поэтому множество спецификатора рассматривается как множество:

(\dots ((P_{0} \setminus  Q_{n}) \cup  P_{n}) \setminus  \dots  Q_{1}) \cup  P_{1}.

Так, например, переменная W(('ABC'))1 может принимать значения любых термов, кроме символов литер 'A', 'B', 'C', а переменная S(('A')L('0')D)2 может принимать значения любых символов, кроме буквы 'A' и цифры '0'.

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

<имя спецификатора>      S   <спецификатор>

Пусть, например, вводятся имена спецификаторов для операций типа сложения и для операций типа умножения:

ADDOP     S '+-'
MULTOP    S '*/'

Теперь имена спецификаторов, ограниченные с обеих сторон символами двоеточие ":", можно употреблять в спецификациях. Например, переменная S:ADDOP:1 может принимать значения только символов операций типа сложения, а переменная S((:ADDOP::MULTOP:)S)2 может принимать значения всех символов, кроме символов арифметических операций.

Рассмотрим еще 1 пример: функция Separate отделяет от выражения аргумента самый большой идентификатор слева и заключает его в структурные скобки, оставляя неизменным оставшуюся часть выражения. Если же такого идентификатора нет, то функция помечает выражение символом '*'. Решение, основанное на функции Ident не годится, так как нужно знать, где заканчивается идентификатор. Однако если использовать отождествление справа налево, то мы получаем следующее простое решение.

Separate    R   S(L)1 E(LD)2 Ex = (S1 E2) Ex
                             Ex = '*' Ex

Структура рефал-программы и ее модулей

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

Каждая директива находится в отдельной строке и имеет следующий вид:

[<идентификатор>] [<ключевое слово>] [<информация>]

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

Ключевые слова директив приведены в табл. 3.1.

Таблица 3.1.
Ключевое слово Директива Примечание
START Начало модуля(программы) имя директивы модуля (программы)
END Конец модуля (программы) без имени
ENTRY Объявление входов модуля функции модуля, используемые в других модулях
EXTRN Объявление внешних функций функции других модулей, используемые в данном
R Рефал-предложение отождествление справа
L Рефал-предложение отождествление слева (по умолчанию отсутствует)
S Объявление имени спецификатора

Необязательное имя модуля (программы) дается директивой START, а конец модуля (программы) отмечается директивой END без имени (директива начинается с пробела).

Имена всех функций модуля, которые могут быть использованы в других программах и модулях, должны быть объявлены входами директивой ENTER (без имени). Имена функций других модулей, используемых в программе, должны быть объявлены внешними директивой EXTRN. Благодаря директиве EXTRN программа связывается с внешним миром, так как функции ввода исходных данных и вывода результатов описываются на других языках1Такие первичные функции мы опишем в следующем разделе. (ассемблер, С). Модуль может не содержать директивы EXTRN, если он предназначен для использования в других модулях и программах (в этом случае директива ENTRY должна быть обязательно). Имена входов и внешних функций даются их идентификаторами. Но если в одном модуле используется идентификатор внешней функции, отличный от ее описания в другом модуле, то в скобках дается имя этой внешней функции в модуле ее описания.

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

Приведем пример двухмодульной программы.

M1     START 
       ENTRY  COMMUN 
       EXTRN  DREAM 
COMMUN        E1 '+' E2 = k/DREAM/ E1. k/DREAM/ E2. 
       END   
M2     START 
       ENTRY  DREAM       
       EXTRN  общение(COMMUN)  
DREAM         Sx E1 = Sx k/общение/ E1.      
       END

Здесь функция модуля M1 с внутренним именем COMMUN имеет вызов в модуле M2 с внутренним именем "общение".

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

Упражнения

  1. Разработайте рефал-функцию, которая отделяет от выражения самый большой идентификатор справа и заключает его в структурные скобки.
  2. Разработайте спецификатор, который ограничивает множество символов цифрами (кроме 0) и символами-числами.
  3. Разработайте спецификатор, который ограничивает множество термов любыми термами кроме составных символов.
  4. Разработайте рефал-функцию, которая реверсирует последовательность структурных и функциональных термов.
  5. Разработайте двухмодульную программу, один из модулей которой содержит описание функций выделения в стуктурные скобки самого левого идентификатора, переменной, самого левого числа и самой левого символа арифметической операции, а другой модуль производит лексический анализ выражения, определенного аргументом у функции лексического анализа, функция которого описана с помощью функций первого модуля.
< Лекция 2 || Лекция 3 || Лекция 4 >