- •Основы конструирования компиляторов
- •Введение. Трансляция арифметических выражений. Метод Рутисхаузера
- •1Основные понятия и определения
- •1.1Классификация компилирующих программ
- •1.2Синтаксис и семантика. Структура компилятора
- •2Формальные грамматики и их использование при лексическом и синтаксическом анализе
- •2.1Формальная грамматика и формальный язык
- •2.2Понятие грамматического разбора
- •2.3Расширенная классификация грамматик Хомского
- •2.4Распознавание регулярных грамматик
- •2.4.1Конечный автомат и его программная реализация
- •2.4.2Построение лексических анализаторов
- •2.4.3Построение синтаксических анализаторов
- •2.5Распознавание кс-грамматик
- •2.5.1Автомат с магазинной памятью
- •2.5.2Синтаксические анализаторы ll(k)-грамматик. Метод рекурсивного спуска
- •2.5.3Синтаксические анализаторы lr(k)-грамматик. Грамматики предшествования
- •2.6Польская запись. Алгоритм Бауэра-Замельзона
- •3Распределение памяти
- •4Генерация и оптимизация кодов
- •1 Основные понятия и определения 3
- •2 Формальные грамматики и их использование при лексическом и синтаксическом анализе 5
- •3 Распределение памяти 27
- •4 Генерация и оптимизация кодов 28
2.6Польская запись. Алгоритм Бауэра-Замельзона
Результат синтаксического анализа – дерево грамматического разбора – представляют в виде таблицы или обратной польской записи.
Польская запись (в честь польского математика Лукасевича, предложившего этот вид записи выражений) представляет собой последовательность команд двух типов:
КI, где I – идентификатор операнда – выбрать число по имени I и заслать его в стек операндов;
K, где – операция – выбрать два верхних числа из стека операндов, произвести над ними операцию и занести результат в стек операндов.
Рассмотрим алгоритм Бауэра-Замельзона, по которому осуществляется представление выражений в виде польской записи.
Алгоритм Бауэра-Замельзона. Грамматика, описывающая правила записи арифметических выражений, относится к классу грамматик операторного предшествования, т. е. порядок следования терминальных символов (знаков операций), однозначно определяет порядок выделения троек, причем нетерминальные символы (имена операндов) на этот порядок не влияют.
Синтаксический распознаватель выражений в процессе разбора должен формировать запись, по которой затем выполняется генерация кода. В качестве такой записи часто используют обратную польскую запись.
Согласно алгоритму Бауэра-Замельзона разбор выражения и формирование польской записи выполняется в два этапа:
разбор выражения и построение эквивалентной польской записи;
выполнение (или трансляция) польской записи.
При этом используется два стека: стек операций – на первом этапе и стек операндов – на втором этапе.
Построение польской записи выполняется следующим образом: транслятор читает выражение слева направо и вырабатывает последовательность команд по следующему правилу:
а) если символ – операнд, то вырабатывается команда КI,
б) если символ – операция, то выполняются действия согласно таблице 11:
Таблица
11 – Таблица генератора
\
+
*
(
)
I
I
I
?
Вых
+
II
I
I
IV
IV
*
IV
II
I
IV
IV
(
I
I
I
III
?
Обозначения:
? - ошибка;
- верхний символ в стеке операций;
- текущий символ.
Операции:
I – заслать в стек операций и читать следующий символ;
II – генерировать K , заслать в стек операций и читать следующий символ;
III – удалить верхний символ из стека операций и читать следующий символ;
IV – генерировать K и повторить с тем же входным символом.
На этапе выполнения польская запись читается слева направо и выполняется.
Польская запись может использоваться как промежуточная форма не только для выражений, но и для других операторов. Соответственно при этом для получения записи должен использоваться модифицированный алгоритм Бауэра-Замельзона.
Пример. Построить тройки для выражения (a+b*c)/d.
Построение польской записи:
Стек операций |
Символ |
Действие |
Команда |
► |
( |
I |
|
► ( |
a |
|
Ka |
► ( |
+ |
I |
|
► ( + |
b |
|
Kb |
► ( + |
* |
I |
|
► ( + * |
c |
|
Kc |
► ( + * |
) |
IV |
K* |
► ( + |
) |
IV |
K+ |
► ( |
) |
III |
|
► |
/ |
I |
|
► / |
d |
|
Kd |
► / |
|
IV |
K/ |
► |
|
Конец |
|
В результате получаем:
Ka Kb Kc K* K+ Kd K/ или abc*+d/
Выполнение операций:
Стек операндов |
Команда |
Тройка |
|
Ka |
|
a |
Kb |
|
a b |
Kc |
|
a b c |
K* |
T1= b*c |
a T1 |
K+ |
T2= a+T1 |
T2 |
Kd |
|
T2 d |
K/ |
T3= T2/d |
T3 |
|
|
