Россия, г. Магнитогорск |
Язык РЕФАЛ: простейшие конструкции Рефала-2
Рефал-функции
Вызов рефал-функции описывается как функциональный терм и имеет следующий синтаксис:
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', а все четные символы на символ '0'.
- Разработайте рефал-функцию, которая ликвидирует все структурные и функциональные скобки в выражении аргумента.