Uploaded by dtorbol

Ref

advertisement
Развитие модели Маркова и обзор языка РЕФАЛ
В 60-х годах прошлого века русским информатиком В.Ф.Турчиным вместе с учениками в ИПМ АН СССР был
разработан новый язык Рефал (REFAL - REcursive Functional Algorithmic Language), который является
развитием модели нормальных алгоритмов Маркова в направлении структурирования элементов языка НАМ.
Модификациями языка НАМ, введенными в Рефал, явились следующие структуры:
1.
Вместо произвольной строки данных рассматривается рефал-выражение - строка, сбалансированная
по скобкам (символьным, структурным, составным и функциональным). Рефал-выражение в
функциональных скобках, не содержащее других функциональных скобок,
называется функциональным термом .
2.
Вместо марковской подстановки вводится рефал-предложение, отличающееся тем, что в левой части
находится рефал-выражение, быть может содержащее переменные, которые употребляются в правой
части. При поиске подходящего рефал-предложения делается попытка интерпретации переменных, при
которой получающийся в левой части рефал-предложения функциональный терм входит в выражение
данных. В таком случае он заменяется в этом выражении на правую часть рефал-предложения с этой
же интерпретацией переменных. Тем самым одно рефал-предложение может заменять много
марковских подстановок.
3.
Множество рефал-предложений также структурируется - объединяется в структуру рефалфункции. Функциональный терм как раз и представляет собой вызов рефал-функции с
выражением аргументов (несколько аргументов функции при вызове рассматриваются как одно
выражение). При таком вызове рефал-функции проверяется существование интерпретации
переменных ее рефал-предложений в порядке их следования. Как правило, одно из рефалпредложений должно быть обязательно подходящим для выражения данных аргумента рефал-функции.
Результатом выполнения рефал-функции может быть любое рефал-выражение. В частности, в
результирующем выражении может быть функциональный терм - вызов другой или той же самой рефалфункции (рекурсивность). Вызовы рефал-функций могут быть вложены друг в друга, и при этом
аргументами одних рефал-функций могут быть результаты выполнения вложенных рефал-функций.
4.
Рефал-программа представляет собой некоторую последовательность директив языка, из которых
наиболее важными являются директива, задающая последовательность вызовов рефал-функций,
и директивы, задающие описания рефал-функций. Выполнение рефал-программы определяется вызовом
рефал-функций.
Во второй половине XX века был разработан целый ряд версий Рефала, из которых основные:
базовый Рефал, Рефал-2, Рефал-4, Рефал-5 и Рефал-6 (является модификацией версии Рефал-5). Все версии
в качестве ядра содержат базовый Рефал, но если целью первых версий была направленность на разработку
алгоритмов синтаксического анализа языков программирования, то последние версии Рефала не только
работают под операционной системой Windows, но и имеют ряд современных конструкций, позволяющих
вводить объектные конструкции в этот язык, легче разрабатывать реализацию сложных по логике
вычислительных алгоритмов, взаимодействовать с современными языками создания дизайна интернетприложений (такими, как Java), создавать HTML-редакторы. Ввиду ограниченности объема учебного пособия
идеи, положенные в язык Рефал, мы сначала дадим на базовом Рефале и версии Рефал-2, а затем опишем
отличия современной версии Рефала - Рефала-5. Для более полного описания мы отсылаем интересующихся
к специальной литературе и соответствующим многочисленным интернет-сайтам.
Перейдем теперь к последовательному описанию основных конструкций Рефала-2 (в дальнейшем
просто Рефала), но прежде сделаем одно замечание: в синтаксисе Рефала везде, где отдельные
синтаксические конструкции разделяются, может стоять сколько угодно пробелов.
Рефал-выражения
Любое данное Рефала представляет собой некоторую последовательность знаков. Однако некоторые знаки
имеют специальное фиксированное значение в синтаксисе языка и представляют скобки, типы, разделители.
К ним относятся:
1.
Cимвольные скобки - апострофы. Любой знак, помещенный в апострофы, является символом. Например,
'A', 'B', 'C' - это 3 символа. Знак апостроф тоже может быть символом, но тогда для отличия его от
окружающих апострофов он удваивается. Например, "" - это символ апостроф. Несколько подряд
идущих символов могут объединяться в цепочку символов, и тогда апострофы можно писать в начале и
в конце цепочки. Символы и цепочки являются выражениями. Например, цепочка из 4 символов 'A' 'B' "
'C' может быть записана как 'AB"C'.
2.
Составные скобки - знак косой черты "/". Они используются для образования составных символов,
которыми являются символы-метки, символы-числа и символы-ссылки.
Символом-меткой является любой идентификатор (последовательность букв, цифр и знака "-",
начинающаяся с буквы), помещенный в составные скобки. Так например, /это-метка-/ и /aLpha/ - 2
символа-метки.
Символом-числом является любая последовательность цифр, помещенная в составные скобки.
Например, /0/, /1024/ - 2 символа-числа.
Символом-ссылкой является последовательность знака "%" и 8 16-ричных цифр, помещенная
в составные скобки. Например, /%12ef34ab/, /%ffffffff/ - 2 символа-ссылки.
Символами являются как символы знаков, так и составные символы (числа, метки, ссылки).
3.
Структурные скобки - круглые скобки. Они используются для структуризации выражений, и в них
должно находиться любое рефал-выражение, в том числе и пустое. Например, (('A/') 'С' ()) выражение, которое в свою очередь содержит 3 выражения: цепочку 'A/', символ 'С' и пустое
выражение.
Любое выражение в структурных скобках, не содержащее других структурных скобок, называется
структурным термом.
4.
Функциональные скобки - знак "k" для открывающей скобки и точка "." для закрывающей скобки.
Например, k/Summa/ (x) y. В этом примере вызывается функция с идентификатором Summa и 2
аргументами-выражениями (x) и y.
Любое выражение в функциональных скобках, не содержащее других функциональных скобок,
называется функциональным термом.
5.
6.
Знак равно "=" используется для разделения левой и правой частей рефал-предложения (аналог знака
"
" в марковской подстановке).
Буквы S, W, V, E, s, w, v, e используются для указания типа в синтаксисе переменной рефалвыражения (см. раздел Переменные).
Рефал-выражение - это последовательность символов, переменных (см. следующий раздел) и скобок,
сбалансированная по скобкам. Это означает, что внутри скобок какого-либо типа также должно
стоять выражение, сбалансированное по скобкам или вовсе без скобок (пустое выражение).
Например, выражение
(k/Summa/ (/123/) k/Func/ /Две-порции/..)
- сбалансировано по скобкам (внутри первых структурных скобок находятся функциональные, а внутри них
находится последовательность из



составных скобок с идентификатором функции Summa,
структурных скобок, внутри которых символ-число 123,
функциональных скобок, внутри которых 2 символа-метки (идентификатор функции Func и аргумент этой
функции)).
Строка (k/Summa/ (/123/) k/Func/ /Две-порции/).). не является рефал-выражением, хотя
открывающие и закрывающие скобки по каждому отдельному типу правильно расположены, но внутри первых
структурных скобок не находится рефал-выражение: вторая открывающаяся функциональная скобка не имеет
соответствующей закрывающейся функциональной скобки.
Рефал-выражениями должны быть исходные данные, части любого рефал-предложения и результаты вызова
функции, а также директива последовательности вызов функций.
Термом называется рефал-выражение, которое является либо символом (знака или составным), либо
переменной, либо структурным или функциональным термом. Таким образом, рефал-выражение - это
последовательность из любого числа термов (в том числе и нулевого - пустое выражение).
Рефал-функции
Вызов рефал-функции описывается как функциональный терм и имеет следующий синтаксис:
k/<{имя функции}>/<{выражение-аргументов}>.
При этом в выражении аргументов выражения каждого из аргументов (если их несколько) разделяются
пробелами.
Описание рефал-функции имеет следующий синтаксис:
<имя функции>
<рефал-предложение 1>
<рефал-предложение 2>
.....................
<рефал-предложение n>
Началом описания функции является ее имя (в отдельной строке без пробелов слева - директива описания).
Каждое рефал-предложение записывается в отдельной строке (после хотя бы одного пробела слева).
Допускается первое рефал-предложение описания функции писать в строке имени функции. Концом описания
функции является директива описания следующей функции или директива конца программы.
Рефал-предложение имеет следующий синтаксис:
<рефал-выражение 1>=<рефал-выражение 2>
Здесь в рефал-выражение 2 могут входить переменные, которые обязательно должны быть определены
в рефал-выражении 1. Область действия этих переменных ограничивается только рефал-предложением (в
другом рефал-предложении могут быть описаны переменные с теми же именами, но имеющими другой
смысл). Говорят, что существует интерпретация переменных, если им можно приписать такое значение (из
допустимого множества значений), при котором рефал-выражение 1 соответствует выражению
аргументов при вызове функции (при установлении соответствия пробелы, разделяющие синтаксические
единицы как в выражении аргументов, так и в рефал-выражении 1, игнорируются).
Весьма важными являются правила описания переменных, с помощью которых определяется множество
возможных для интерпретации значений переменных. Используются переменные четырех типов:
S -переменные - их значением могут быть только символы;
W -переменные - их значением могут быть только термы;
V -переменные - их значением могут быть только непустые выражения;
E -переменные - их значением могут быть любые выражения (в том числе и пустые).
Заметим, что имеется вложенность множеств переменных:
любая S -переменная является также W -переменной, а любая W -переменная является также V -переменной,
и, наконец, любая V -переменная является также E -переменной.
Любая переменная имеет следующий вид:
<признак типа> [<спецификация>] <индекс>,
где признак типа - одна из четырех букв "S", "W", "V", "E", определяющая тип переменной,
а индекс является цифрой или буквой и служит для отличия различных переменных в одном рефалпредложении. Например, S1, SA, Wx, V2, E3 - 5 переменных.
Спецификация определяет ограничение на множество значений переменных при поиске интерпретации.
Если она отсутствует, то переменная может принимать любые значения, соответствующие типу переменной.
Так, в предыдущем примере переменные S1 и SA могут принимать значения любого из
символов, переменная Wx может принимать значения любого символа, числа, имени, ссылки или любого
терма, переменная V2 - значение любого непустого выражения, а переменная E3 - также и значение пустого
выражения.
Правила определения спецификаций мы рассмотрим в следующем разделе. А пока приведем несколько
примеров.
Пример 1. Необходимо написать функцию First-symbol, которая в качестве значения возвращает первый
символ выражения аргумента. Так, при вычислении функционального терма
k/First-symbol/
'Z'('AB')'+F'.
она должна возвратить символ 'Z'. "Решение", основанное на таком виде аргумента, будет следующим:
First-symbol
S1 Ex = S1
поскольку возможна единственная интерпретация переменных:
S1 <- 'Z'
Ex <- ('AB')'+F'.
Это решение для вызова
k/First-symbol/
/123/'+F'.
возвратит число /123/. Однако, если аргументом вызова функции будет рефал-выражение ('AB')'+F', не
найдется ни одной интерпретации, так как структурная скобка "(" не является символом '('. Поэтому
правильное решение нужно дополнить предварительным снятием структурных скобок, которые могут
присутствовать в выражении аргумента (этого делать было бы не надо, если бы выражение аргумента имело,
например, ограничение: отсутствуют структурные скобки). Приведем такое решение:
First-symbol
S1 Ex = S1
(E1) Ex = k/First-symbol/E1
=
Ex.
В этом решении в случае выражения аргументов без структурных скобок будет применяться первое рефалпредложение описания функции. А в случае, когда выражение аргумента начинается со структурной скобки,
правильную интерпретацию получает только второе рефал-предложение, которое снимает скобки и снова
вызывает ту же функцию (рекурсивность) и т.д. до тех пор, пока первым не окажется первый символ (тогда
будет применено первое рефал-предложение). Необходимость последнего рефал-предложения в описании
функции (с пустой левой и правой частью) вызвана тем, что выражение аргумента может не содержать ни
одного символа и, значит, быть пустым. В этом случае функция возвращает пустое выражение.
Пример 2. Для следующего вызова функции
k/F/
'A1:=B1;A2:=B2;A3:=B3'.
имеется следующее ее описание:
F
E1 ';' E2 = k/G/ E1.
k/F/ E2.
Это означает, что выражение аргумента делится на 2 выражения, первое из которых обрабатывается
функцией G, а второе - той же функцией F. Но при отождествлении левой части рефал-предложения с
выражением аргумента возможны 2 интерпретации:
E1 <- 'A1:=B1'
E2 <- 'A2:=B2;A3:=B3'
и
E1 <- 'A1:=B1;A2:=B2'
E2 <- 'A3:=B3'
Такая неоднозначность может возникать в случае, когда рефал-предложение имеет несколько переменных
типов V и E (назовем такие переменные VE -переменными). Для устранения неоднозначности используются 2
метода отождествления: слева направо и справа налево.
При отождествлении слева направо выбирается интерпретация, при которой самая левая VE переменная принимает самое короткое значение. Если это не устранит неоднозначности, то так же
производится интерпретация для второй и т.д. переменных. В примере 2 будет в этом случае выбрана
первая интерпретация. Этот метод отождествления применяется по умолчанию. Функция F после первого
применения выдаст результат:
k/G/ 'A1:=B1'.
k/F/ 'A2:=B2;A3:=B3'.
При отождествлении справа налево выбирается интерпретация, при которой самая правая VEпеременная принимает самое короткое значение. Если это не устранит неоднозначности, то так же
производится интерпретация для второй и т.д. переменных. В примере 2 будет в этом случае выбрана
вторая интерпретация. Для указания отождествления справа налево необходимо перед левой частью рефалпредложения поместить ключевое слово "R" (знак R, за которым идет хотя бы 1 пробел). В примере 2 в этом
случае следует написать:
F
R E1 ';' E2 = k/G/ E1.
k/F/ E2.
и результатом замены будет выражение
k/G/ 'A1:=B1;A2:=B2'.
k/F/ 'A3:=B3'.
Упражнения
1.
Разработайте рефал-функцию, которая возвращает последний символ аргумента, если он есть, или
пустую строку в противном случае.
2.
Разработайте рефал-функцию, которая возвращает первый и последний символ аргумента, если они не
совпадают, или пустую строку в противном случае.
3.
Разработайте рефал-функцию, которая возвращает цепочку символов, симметрично расположенных в
аргументе относительно центра цепочки.
4.
Разработайте рефал-функцию, которая реверсирует цепочку символов (первый символ становится
последним, второй - предпоследним и т.д.).
5.
Разработайте рефал-функцию, которая заменяет в цепочке символов аргумента все нечетные символы
на символ '1', а все четные символы на символ '0'.
6.
Разработайте рефал-функцию, которая ликвидирует все структурные и функциональные скобки в
выражении аргумента.
Download