Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Синтаксически управляемый перевод
На практике СиА, СеА и генерация внутреннего представления программы осуществляется часто одновременно. Способ построения промежуточной программы – синтаксически управляемый перевод. В его основе лежит грамматика с действиями. Параллельно с анализом исходной цепочки лексем осуществляются действия по генерации внутреннего представления программы. Для этого грамматика дополняется вызовами соответствующих процедур. Пример 2.17. Составим процедуры перевода в ПОЛИЗ программы на М языке. ПОЛИЗ представляет собой массив, каждый элемент которого является парой вида (n, k), где n – номер таблицы лексем, k – номер лексемы в таблице. Расширяем набор лексем: 1) в таблицу ограничителей добавляем новые операции ! (18), !F (19), R (20), W (21); 2) для ссылок на номера элементов ПОЛИЗа введем нулевую таблицу лексем, т.е. пара (0, p) - это лексема, обозначающая p-ый элемент в ПОЛИЗе; 3) чтобы различать операнды-переменные и операнды-адреса переменных, обозначим переменные как четвертую таблицу лексем, а адреса – пятую. Введем следующие обозначения переменных и процедур: 1) Р – переменная–массив, в который размещается генерируемая программа; 2) free – переменная, хранящая номер первого свободного элемента в массиве P; 3) LEX – переменная, хранящая очередную лексему; 4) put _ lex(LEX) – запись очередной лексемы в массив P, т.е. P[free]:=LEX и free:=free+1; 5) put _ l – запись текущей лексемы в массив P; 6) put _ l 5 – запись текущей лексемы в массив P с изменением четвертого класса лексем на пятый; 7) put _ op - запись в массив P знака операции, считанного процедурой checkop; 8) make(k) - процедура, формирующая лексему-метку (0, k).
Правила, описывающие выражения языка М, с учетом действий перевода в ПОЛИЗ принимают вид.
Е ® Е1 {( > | < | = ) <instl> E1 <checkop; put_op >} E1® Т {(+ | - | Ú) <instl> T <checkop; put_op >} T ® F {( * | / | Ù) <instl> F<checkop; put_op >} F® I <checkid; put_l> | N <inst(‘int’); put_l> | L <inst(‘bool’); put_l>| ØF <checknot; put_lex(‘Ø’)>| (E)
Оператор присваивания, дополненный действиями, примет вид:
S® I <checkid; put_l5> := E <eqtype; put_lex(‘:=’)>
При генерации ПОЛИЗа выражений и оператора присваивания элементы массива Р записываются последовательно. Семантика условного оператора такова, что значения операндов для операций безусловного перехода и перехода «по лжи» в момент генерации еще не неизвестны. Поэтому необходимо запоминать номера элементов массива Р, соответствующих этим операндам, а затем, когда станут известны их значения, заполнять пропущенное. Правила условного оператора и оператора цикла примут вид:
S® if E <egbool; p1:=free; free:=free+1; put_lex(‘!F’)> then S <p2:=free; free:=free+1; put_lex(‘!’); P[p1]:=make(free)> else S <P[p2]:=make(free)> S® while <p0:=free> E <egbool; p1:=free; free:=free+1; put_lex(‘!F’)> do S <P[free]:=make(p0); put_lex(‘!’); P[p1]:=make(free) >
Правила операторов ввода и вывода с учетом действий записи в ПОЛИЗ будут преобразованы следующим образом:
S® write (E <put_lex(‘W’)>) | read (I <checkid; put_l5; put_lex_(‘R’)> )
Чтобы в конце ПОЛИЗа была точка, правило Р переписывается в виде: P®program D1 B <put_lex(‘.’)>. Таким образом, польская инверсная запись очищена от всех служебных слов, кроме true и false; от ограничителей остаются только знаки операций и знаки «:=», «.».
Интерпретатор программы
Запись программы в форме ПОЛИЗа удобна для последующей интерпретации (выполнения программы) с помощью стека. Массив ПОЛИЗа просматривается один раз слева направо, при этом: 1) если очередной элемент ПОЛИЗа является операндом, то его значение заносят в стек; 2) если очередной элемент – операция, то на «верхушке» стека находятся ее операнды, которые извлекаются из стека, над ними выполняется соответствующая операция, результат которой заносится в стек; 3) интерпретация продолжается до тех пор, пока не будет считана из ПОЛИЗа точка, стек при этом должен быть пуст. Пример 2.18. Интерпретировать ПОЛИЗ программы, заданный таблицей 2.5 при введенном значении а равном 7.
Таблица 2.5 – ПОЛИЗ исходной программы
Продолжение таблицы 2.5 – ПОЛИЗ исходной программы
Процесс интерпретации программы на модельном языке М, записанной в форме ПОЛИЗа, показан в таблице 2.6.
Таблица 2.6 – Ход интерпретации ПОЛИЗа программы
Стек |
Текущий элемент ПОЛИЗа |
Операция | Таблицы переменных | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
адреса | значения | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
пуст | 1 | адрес - в стек | 1) a 2) b | 1) - 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 | 2 | извлечь из стека номер элемента таблицы значений и записать по нему число 7 | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
пуст | 3 | значение - в стек | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
7 | 4 | значение - в стек | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
7; 5 | 5 | в стек – true, т.к. 7>5 | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
true | 6 | метка - в стек | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
true; 6 | 7 | переход, к следующему элементу ПОЛИЗа, т.к. условие истинно | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
пуст | 8 | адрес - в стек | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 | 9 | значение переменной - в стек | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2; 7 | 10 | число - в стек | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2; 7; 3 | 11 | извлечь из стека 3 и 7 и поместить в стек их сумму | 1) a 2) b | 1) 7 2) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2; 10 | 12 | присвоить второму элементу таблицы значений число 10 | 1) a 2) b | 1) 7 2) 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
пуст | 13 | значение – в стек | 1) a 2) b | 1) 7 2) 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
10 | 14 | вывести на экран число из «верхушки стека» | 1) a 2) b | 1) 7 2) 10 |
Продолжение таблицы 2.6 – Ход интерпретации ПОЛИЗа программы
Стек |
Текущий элемент ПОЛИЗа |
Операция | Таблицы переменных | |
адреса | значения | |||
пуст | 15 | метка – в стек | 1) a 2) b | 1) 7 2) 10 |
19 | 16 | переход к элементу ПОЛИЗ с номером, извлекаемым из верхушки стека | 1) a 2) b | 1) 7 2) 10 |
пуст | 19 | интерпретация завершена | 1) a 2) b | 1) 7 2) 10 |
Пример 2.19. Построим интерпретатор ПОЛИЗа для языка М.
Введем следующие обозначения процедур и функций:
1) ad d r(1) – функция, выдающая адрес ячейки, отведенной для хранения лексемы l;
2) cont(А) – функция, выдающая содержимое ячейки с адресом А;
3) let(А, х) – процедура записи в ячейку с адресом А значения х;
4) inst(x) – процедура записи в стек значения х;
5) o u tst(x) – процедура считывания из стека значения х.
Тело интерпретатора ПОЛИЗа будет иметь следующий вид:
free:=1; {на начало P}
repeat
LEX:=P[free]; {очередная лексема}
n:=LEX[1]; k:=LEX[2];
case n of
0: inst(k); {метка - в стек}
5: inst(addr(LEX)); {адрес - в стек}
1,3,4: inst(cont(addr(LEX))); {значение - в стек}
2: {знак операции}
case k of
8{+}: begin outst(у); outst(x); inst(x+y) end;
9{-}: begin outst(у); outst(x); inst(x-y) end;
…{аналогично для *, / и других операций}
14{Ø}: begin outst(x); inst(not x) end;
5{:=} begin outst(x); outst(А); let(А, х) end;
18{!}: begin outst(free); free:=free-1 end;
19{!F}: begin
outst(free1); outst(B);
if B=false then free:=free1-1;
end;
20{R}: begin outst(A); read(x); let(А, х) end;
21{W}: begin outst(x); write(x) end
end
end
free:=free+1;
until (k=2) and (n=2).
Последнее изменение этой страницы: 2019-06-09; Просмотров: 197; Нарушение авторского права страницы