- •5.2. Ll(1)-метод синтаксического анализа.
- •Отношения между классами кс-грамматик
- •1.Семантический анализ
- •1.1. Польская инверсная запись
- •1.2.Интерпретация полиЗа
- •1.3.Генерирование команд по полиЗу
- •1.4.Алгоритм Замельсона и Бауэра перевода выражений в полиз
- •7.5. Атрибутные грамматики
- •Генерация кода Свойства языка внутреннего представления программы.
- •Синтаксически управляемый перевод на примере перевода арифметического выражения в полиз.
- •Представление условных операторов, операторов цикла и оператора безусловного перехода в полиз.
- •Генерация кода на языке ассемблер, для вычисления арифметического выражения.
- •Генерация кода для операторов read и write языка паскаль.
- •Генерация кода для условного оператора if, вложенного оператора if языка паскаль.
- •Генерация кода для оператора цикла for, вложенного оператора for языка паскаль.
- •Генерация кода для операторов цикла while, repeat языка паскаль.
Синтаксически управляемый перевод на примере перевода арифметического выражения в полиз.
Продолжая рассмотренный алгоритм, приведём реальный пример перевода выражения с языка Паскаль в обратную польскую запись.
Для этого сделаем несколько дополнений, в частности мы можем ввести операции с наивысшим приоритетом:
Оператор |
Приоритет |
:= |
101 |
^,. |
0 |
Так как выражение присваивания обычно имеет вид <переменная>:= <выражение>, то приоритет операции присваивания должен быть менее приоритета скобок, а приоритет операций ссылки по указателю, и ссылки на структуру наивысший. Отдельно отметим, что операция адресации "@" прямо не является операцией, а лишь префиксом, который отменяет последнюю адресацию, хотя при соответствующем генераторе кода с возможностью отмены последней ссылки адресация может быть обработана как обычная операция в стеке.
Последний штрих - после конца строки мы выталкиваем оператор присваивания неким фиктивным оператором, приоритет которого менее приоритета оператора присваивания.
Для исполнения выражения, записаного в обратной польской записи необходима организация арифметического стека. Арифметический стек используется для хранения промежуточных результатов. Переменные (их значения), встречающиеся в правой части выражения заносятся на стек, операторы преобразовывают верхние два, три или одно число в результат, операнды снимаются со стека и туда помещается результат. Оператор присваивания снимает со стека адрес переменной и значение, которое надо поместить по этому адресу. Детальнее расмотрим алгоритм генерации кода через раздел.
Представление условных операторов, операторов цикла и оператора безусловного перехода в полиз.
Условные операторы, операторы цикла и операторы безусловного перехода довольно легко представляются в обратной польской записи. В любом случае внутри этих операторов лежат безусловный и условный переходы. Безусловный переход достаточно просто определяется - как в соответствующем языке ассемблера
JMP метка
оператор условного перехода требует большей работы. Вспомним, что любое логическое выражение оставляет на арифметическом стеке булево значение, обычно не нуль или нуль. Таким образом фрагмент программы может выглядеть так:
pop ax test ax,ax jnz метка_перехода
Генерация кода на языке ассемблер, для вычисления арифметического выражения.
Одно важное свойство, присущее генерации кода для выражения в обратной польской записи, это то, что код строится последовательно, фактически дописывая кусочек кода за кусочком, соответствующий семантике данного выражения.
Рассмотрим таблицу случаев генерации кода для процессора 8086/8087, для случая - один для 8086, другой для сопроцессора 8087. Условимся, что вершина арифметического стека кешируется в 8086 процессоре в регистре bx.
Действие |
Код для 8086 |
Код для 8087 |
:= |
pop ax ; адрес xchg ax,bx mov [bx],ax ; двигаем |
fstp dword ptr [bx]; в bx адрес pop bx |
Внесение левой части в стек (или любого адреса) |
push bx mov bx, offset var |
|
Внесение переменной в стек |
push bx mov bx, var |
fld var |
Унарный минус |
neg bx |
fchs |
Бинарная операция: вычитание |
pop ax xchg ax,bx sub bx,ax |
fsub |
Бинарная операция: сложение |
pop ax add bx,ax |
fadd |
Ссылка по адресу |
mov bx,[bx] |
|
Ссылка на структуру |
mov bx,[bx+offset field] |
|
Тернарная условная операция |
test bx,bx pop bx pop ax jz exit1 xchg ax,bx exit1: ... |
fistp temp wait mov ax,temp and ax,ax jz exit2 fxch exit2: fincstp ffree st |
Загрузка значения по адресу |
mov bx, [bx] |
fld dword ptr [bx] |
Вообще, есть немало способов реализации генерации кода для выражения, записанного в обратной польской записи. В любом случае, на основании этой таблицы можно придумать аналогию для любого процессора.
