Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Синтаксически управляемый перевод



 

На практике СиА, СеА и генерация внутреннего представления программы осуществляется часто одновременно. Способ построения промежуточной программы – синтаксически управляемый перевод. В его основе лежит грамматика с действиями. Параллельно с анализом исходной цепочки лексем осуществляются действия по генерации внутреннего представления программы. Для этого грамматика дополняется вызовами соответствующих процедур.

Пример 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 >}

EТ {(+ | - | Ú) <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 – ПОЛИЗ исходной программы

 

Лексема a r a 5 > 17 !F b a 3 +
(n, k) (5,1) (2,20) (4,1) (3,1) (2,16) (0,17) (2,19) (5,1) (4,1) (3,2) (2,8)
Номер 1 2 3 4 5 6 7 8 9 10 11

Продолжение таблицы 2.5 – ПОЛИЗ исходной программы

Лексема := b W 19 ! a W .
(n, k) (2,5) (4,1) (2,21) (0,19) (2,18) (4,1) (2,21) (2,1)
Номер 12 13 14 15 16 17 18 19

Процесс интерпретации программы на модельном языке М, записанной в форме ПОЛИЗа, показан в таблице 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; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.027 с.)
Главная | Случайная страница | Обратная связь