
- •1.Прямые методы трансляции
- •1.1.Сущность польской записи
- •1.2.Перевод в опз арифметических и логических выражений
- •1.3.Перевод в опз переменных с индексами
- •1.4.Получение опз для указателей функций
- •1.5.Получение опз для оператора присваивания
- •1.6.Получение опз для условного оператора
- •1.7.П олучение опз для оператора цикла for
1.Прямые методы трансляции
Из несинтаксических методов рассмотрим распространенный метод получения обратной польской записи.
1.1.Сущность польской записи
Способы записи выражений - прямая и обратная польские записи названы так в честь польского математика Яна Лукашевича.
Р
ассмотрим
сущность обратной польской записи на
примере:
Выражение a + b * c – d / (a + b) можно графически представить в виде дерева операций:
Здесь узлы – операции, а ветви – операнды. Левая ветвь – левый операнд, а правая – правый. В каждой ветви операциям, которые выполняются раньше, соответствуют нижележащие узлы. Корневая операция выполняется последней.
Если, начав с нижнего листа самой левой ветви, обойти все листья и узлы так, чтобы ветви рассматривались слева направо, а узел рассматривался только после обхода всех исходящих из него ветвей, как показано стрелками на рисунке, то получится обратная польская запись (ОПЗ): a b c * + d a b + / - .
Если используются только бинарные операции, то такой обход дает следующая рекурсивная процедура:
procedure tree(v);
begin
if v.term then print(v.value)
else begin
tree(v.left)
tree(v.right)
print(v.value)
end;
end;
ОПЗ называют также постфиксной записью. Операнды в ОПЗ располагаются в том же порядке, что и в исходном выражении, а знаки операций при просмотре записи слева направо встречаются в том порядке, в котором нужно выполнять соответствующие действия. В ОПЗ отсутствуют скобки.
Таким образом, выражение можно вычислить в процессе однократного просмотра слева направо.
Если элемент – операнд, то переходим на следующий элемент. Если элемент – знак операции, то она выполняется над операндами, записанными слева от знака операции. Результат записывается вместо операндов и операции, которые вычеркиваются. Просмотр продолжается. В результате останется один элемент – значение выражения.
Аналогично можно записывать и вычислять булевские выражения.
Выражение a + b > - 5 and z - d = 1 + q ^ 2 представляется деревом:
О
бход
дерева дает ОПЗ a b
+ 5 из z d –
1 q 2
+ = and .
И
ногда
применяют прямую польскую запись
(ППЗ) – префиксную запись.
a
b
c
d
a
b
У злы обходятся так, чтобы верхний узел рассматривался раньше нижнего, и сразу после рассмотрения очередного узла просматривались слева направо исходящие из него ветви.
Получается + a * b c / d + a b .
В рекурсивной процедуре обхода дерева операций будет сначала выведен знак операции, а потом рассматриваются ветви-операнды.
print(v.value)
tree(v.left)
tree(v.right)
Выражения, записанные в ППЗ, вычисляются справа налево.
1.2.Перевод в опз арифметических и логических выражений
Метод, который мы с вами рассмотрим, был предложен в 1960 году голландским ученым, которого зовут Эдсгер Вибе Дейкстра (Edsger Wybe Dijkstra).
Он основан на использовании стека с приоритетами, позволяющего изменить порядок следования знаков операций в выражении так, что получается обратная польская запись.
Каждому ограничителю, входящему в выражение, присваивается приоритет.
Приоритеты |
Ограничители |
0 1 2 3 4 5 6 7 8 9 10 |
{ ( [ begin if for Ф } ) ] end then else to do , ; := goto OR AND NOT > ≥ = ≠ < ≤ + - * / mod div ИЗ ^ exit, halt |
Операция ИЗ – изменение знака, а Ф – вызов функции .
Арифметическое выражение просматривается слева направо.
Операнды переписываются в выходную строку, а знаки операций помещаются в стек операций.
Выходная строка Операнды Входная стока
Знак операции
Стек операций
Если приоритет входного знака равен 0 или больше приоритета знака находящегося в вершине стека или стек пустой, то новый знак добавляется к вершине стека. В противном случае из стека выталкивается и переписывается в выходную строку знак, находящийся в вершине, а также следующие за ним знаки с приоритетами, большими или равными приоритету входного знака. После того входной знак добавляется к вершине стека.
Особенности имеет лишь обработка скобок. Открывающая круглая скобка просто записывается в стек и не выталкивает ни одного знака. В то же время ее не может вытолкнуть ни один знак, кроме закрывающей скобки. Закрывающая скобка имеет приоритет 1, не превосходящий приоритет любой операции. Поэтому закрывающая скобка вызывает выталкивание всех знаков до ближайшей открывающей скобки включительно. В стек закрывающая скобка не записывается. Открывающая и закрывающая скобки как бы взаимно уничтожаются и в выходную строку не переносятся.
После окончания входной строки происходит выталкивание всех оставшихся в стеке символов и дописывание их к выходной строке.
Пример 1. Привести в обратную польскую запись арифметическое выражение:
a + b * c – d / (a + b)
a b c * + d a b + / -
Пример 2. Перевести логическое выражение
a + b > -5 and z – d = 1 + q ^ 2
a b + 5 ИЗ > z d – 1 q 2 ^ + = and