
- •Обзорная лекция по курсу «языки программирования и методы трансляции»
- •Основная литература
- •1 Описание языка программирования
- •2 Введение в трансляцию
- •3 Способы описания языка
- •4 Формальные языки и грамматики. Основные термины и определения
- •5 Порождающие грамматики (Грамматики н.Хомского1)
- •6 Классификация формальных грамматик
- •7 Автоматные грамматики и конечные автоматы
- •7.1. Механизмы распознавания и преобразования
- •7.2 Конечные автоматы
- •7.3 Способы задания конечных автоматов
- •Контекстно-свободные грамматики и языки
- •Проверка существования языка
- •Удаление бесполезных символов грамматики
- •Эквивалентные преобразования кс-грамматик
- •9.1 Устранение цепных правил
- •Удаление произвольного правила
- •9.3 Левая факторизация правил
- •9.4 Преобразование к нормальной форме Хомского
- •Распознающий автомат для кс- языков (автомат с магазинной памятью)
- •Разнозновидности мп-автоматов
- •11 Методы синтаксического анализа
- •Нисходящий разбор
- •Восходящий разбор
- •12 Генерация внутреннего представления программ
- •12.1 Польская запись
- •2 Алгоритм перевода на промежуточный язык
- •2.1 Полиз как промежуточный язык
2 Алгоритм перевода на промежуточный язык
2.1 Полиз как промежуточный язык
Выберем в качестве языка для представления промежуточной программы постфиксную запись (ее часто называют ПОЛИЗ - польская инверсная запись).
Для перевода в ОПЗ обычно применяют метод стека с приоритетами, разработанный известным ученым Е.Дейкстрой для простых выражений. В этом методе операциям и ограничителям, входящим в выражение, ставятся в соответствие целые числа – приоритеты. Для операции приоритете тем выше, чем старше операция. Стек играет роль своеобразного «отстойника» для операции с более низким приоритетом, чем очередная операция. Особая обработка круглых скобок позволяет избавиться от них.
Польская инверсная запись имеет два важных свойства, которые позволяют использовать ее только для представления выражений, но и в качестве промежуточного языка для языковых процессоров:
действия, описываемые в ПОЛИЗ, можно выполнять (или программировать) в процессе ее одностороннего безвозвратного просмотра слева направо, т.к. операнды в ПОЛИЗ всегда предшествуют знаку операции
операнды ПОЛИЗ расположены в том же порядке, что и в исходном (инфиксном) выражении. Перевод выражения в ПОЛИЗ сводится только к изменению порядка следования знаков операций.
Расширение ПОЛИЗ для представления других конструкций языков программирования (переменных с индексами, указателей функции, условных выражений, основных операторов языка программирования) выполняется очень просто: нужно придерживаться одного правила – знак операции должен следовать непосредственно за соответствующими ему операндами.
В ПОЛИЗе операнды выписаны слева направо в порядке их использования. Знаки операций стоят таким образом, что знаку операции непосредственно предшествуют ее операнды.
Например, обычной (инфиксной) записи выражения
a*(b+c)-(d-e)/f
соответствует такая постфиксная запись:
abc+*de-f/-.
Замечание: обратите внимание на то, что в ПОЛИЗе порядок операндов остался таким же, как и в инфиксной записи, учтено старшинство операций, а скобки исчезли.
Теперь необходимо разработать ПОЛИЗ для операторов входного языка. Каждый оператор языка программирования может быть представлен как n-местная операция с семантикой, соответствующей семантике этого оператора.
Оператор присваивания
I := E
в ПОЛИЗе будет записан как
I E :=
где ":=" - это двухместная операция, а I и Е - ее операнды; I означает, что операндом операции ":=" является адрес переменной I, а не ее значение.
Оператор перехода в терминах ПОЛИЗа означает, что процесс интерпретации надо продолжить с того элемента ПОЛИЗа, который указан как операнд операции перехода.
Чтобы можно было ссылаться на элементы ПОЛИЗа, будем считать, что все они перенумерованы, начиная с 1 (допустим, занесены в последовательные элементы одномерного массива).
Пусть ПОЛИЗ оператора, помеченного меткой L, начинается с номера p, тогда оператор перехода goto L в ПОЛИЗе можно записать как
p !
где ! - операция выбора элемента ПОЛИЗа, номер которого равен p.
Немного сложнее окажется запись в ПОЛИЗе условных операторов и операторов цикла.
Введем вспомогательную операцию - условный переход "по лжи" с семантикой
if (not B) then goto L
Это двухместная операция в операндами B и L. Обозначим ее !F, тогда в ПОЛИЗе она будет записана как
B p F!
где p - номер элемента, с которого начинается ПОЛИЗ оператора, помеченного меткой L.
Семантика условного оператора
if B then S1 else S2
с использованием введенной операции может быть описана так:
if (not B) then goto L2; S1; goto L3; L2: S2; L3: ...
Тогда ПОЛИЗ условного оператора будет таким:
B p2 !F S1 p3 ! S2 ... ,
где pi - номер элемента, с которого начинается ПОЛИЗ оператора, помеченного меткой Li, i = 2,3.
Семантика оператора цикла while B do S может быть описана так:
L0: if (not B) then goto L1; S; goto L0; L1: ... .
Тогда ПОЛИЗ оператора цикла while будет таким:
B p1 !F S p0 ! ... ,
где pi - номер элемента, с которого начинается ПОЛИЗ оператора, помеченного меткой Li, i = 0,1.
Операторы ввода и вывода М-языка являются одноместными операциями. Пусть R - обозначение операции ввода, W - обозначение операции вывода.
Тогда оператор ввода read (I) в ПОЛИЗе будет записан как I R;
оператор вывода write (E) - как E W.
Постфиксная польская запись операторов обладает всеми свойствами, характерными для постфиксной польской записи выражений, поэтому алгоритм интерпретации выражений пригоден для интерпретации всей программы, записанной на ПОЛИЗе (нужно только расширить набор операций; кроме того, выполнение некоторых из них не будет давать результата, записываемого в стек).
Постфиксная польская запись может использоваться не только для интерпретации промежуточной программы, но и для генерации по ней объектной программы. Для этого в алгоритме интерпретации вместо выполнения операции нужно генерировать соответствующие команды объектной программы.
Полиз для представления элементов массива
Пусть требуется вычислить выражение:
(a+b[i, j+1]*c+d), в котором b[i, j+1] – элемент двухмерного массива.
Для представления в постфиксной записи элементов массива необходимо определить дополнительную операцию ПОЛИЗ, вычисляющую адрес элемента массива (код операции SUBS). Операндами операции SUBS являются имя массива и значения индексов. Число операндов этой операции переменно. Оно зависит от размерности массива и определяется по формуле k=n+1, где n – размерность массива. Операнды операции SUBS должны располагаться в определенном порядке: имя массива, значения индексных выражений и константа k (целое без знака), определяющая число операндов.
С учетов представления элементов массива ПОЛИЗ рассматриваемого выражения имеет вид:
a b i j 1+3 SUBS+c*d+
1 Ноам Хомский (р.1928) американский лингвист и политический активист. Начиная с 1957 года опубликовал ряд работ, заложивших основы математической лигвистики.