- •Национальный исследовательский университет «Московский энергетический институт» Институт автоматики и вычислительной техники Кафедра математического моделирования
- •Оглавление
- •Void Prints(rez &r)
- •Void __fastcall tForm1::BitBtn1Click(tObject *Sender)
- •LeksBlok.H
- •Void Strcpy(char mas[], int n, char *txt, int m);
- •Void LeksichBlok(Ident &I, char *txt);
- •LeksBlok.Cpp
- •Void LeksichBlok(Ident &I, char *txt)
- •Sintaksis.H
- •Void Sint(Ident &I, rez &r);
- •Sintaksis.Cpp
- •Void Sint(Ident &I, rez &r)
- •Interpretator.H
- •Void Inter(Ident &I, rez &r);
- •Interpretator.Cpp
- •Void Inter(Ident &I, rez &r)
- •Data.Cpp
- •Ident::Ident()
- •Void Ident::Delete(elem el)
- •Stack_mass.H
Национальный исследовательский университет «Московский энергетический институт» Институт автоматики и вычислительной техники Кафедра математического моделирования
Лабораторная работа №4
«Построение транслятора»
Выполнил студент Киришко Ф.С.
вариант №8 учебной группы А-14-10.
Проверил Анатолий Васильевич Князев
Москва 2012
Задание
Преобразовать заданную грамматику в L-атрибутную транслирующую грамматику в форме простого присваивания.
Разработать атрибутный автомат для трансляции предложений данной грамматики
Разработать программу, реализующую МП-транслятор.
Разработать программу-интерпретатор для данного объектного языка.
Описание языка
Оператор присваивания:
<идентификатор>=<ар.выр>;
Условный оператор:
if(<лог.выр.>)then<оператор>[else<оператор>]
Оператор цикла:
while(<лог.выр.>)
<совокупность операторов>
end_while
Арифметическое выражение:
<E>::=<T><E-список>
<E-список>::=+<T><E-список>
<E-список>::=!
<T>::=<F><T-список>
<T-список>::=*<F><T-список>
<T-список>::=!
<F>::=<P>
<F>::=<R>
<P>::=<Id>
<P>::=<Int>
Логическое выражение:
<лог.выр.>::=<P><лог.опер.><P>
<лог.опер.>::= =
<лог.опер.>::= #
LL-1 грамматика
<S><совок.операторов>
<совок.операторов><оператор><совок.операторов>
<совок.операторов> !
<оператор><операторприсваивания>
<оператор><условныйоператор>
<оператор><операторцикла>
<оператор присваивания>Id= <E>;
<E><T><E-список>
<E-список>+<T> <E-список>
<E-список>!
<T><F><T-список>
<T-список>* <F> <T-список>
<T-список> !
<F><P><F-список>
<F-список>^ <P><F-список>
<F-список> !
<P>Id
<P>Con
<условный оператор>if<лог.выр.>then<оператор><else-часть>
<else-часть>else<оператор>
<else-часть>!
<оператор цикла>for(<Id>=<E>;<лог.выр.>;<Id> = <E>) <совокупность операторов>end
<лог.выр.>(<P><лог.-список>)
<лог.-список>= <P>
<лог.-список># <P>
L – атрибутная транслирующая грамматика в форме простого присваивания для заданного языка
<S><совок.операторов>
<совок.операторов><оператор><совок.операторов>
<совок.операторов> !
<оператор><операторприсваивания>
<оператор><условныйоператор>
<оператор><операторцикла>
<оператор присваивания>Idp1= <E>q1{Присвоитьp2,q2};
p2p1, q2q1
<E>q2<T>p1<E-список>p2,q1
p2 p1, q2 q1
<E-список>p1,t2 +<T>q1 {Сложитьp2,q2,r1} <E-список>r2,t1
p2 p1, q2 q1, (r1, r2) Нов, t2 t1
<E-список>p1,t2!
t2 p1
<T>q2<F>p1<T-список>p2,q1
p2 p1, q2 q1
<T-список>p1,t2 * <F>q1 {Умножитьp2,q2,r1} <T-список>r2,t1
p2 p1, q2 q1, (r1, r2) Нов, t2 t1
<T-список>p1,t2 !
t2 p1
<F>q2<P>p1<F-список>p2,q1
p2 p1, q2 q1
<F-список>p1,t2^ <P>q1{В степеньp2,q2,r1} <F-список>r2,t1
p2 p1, q2 q1, (r1, r2) Нов, t2 t1
<F-список>p1,t2 !
t2 p1
<P>pIdq
pq
<P>pConq
pq
<условный оператор>if<лог.выр.>p1{Переход по 0p2,z1}
then<оператор><else-часть>z2
p2p1, (z1,z2)НовМ
<else-часть>z1else{Безусловный переходw1}{Меткаz2} <оператор> {Меткаw2}
z1 z2, (w1,w2)НовМ
<else-часть>z1{Меткаz2}
z2z1
<оператор цикла>for(<Idp1>=<Eq1>{Присвоитьp2,q2};<лог.выр.t1>;<Idr1> = <Es1>){Меткаz1} {Переход по сравнениюt2,w1} <совокупность операторов> {Присвоитьr2,s2} {Безусловный переходz2} {Меткаw2}end
p2p1,q2q1,t2t1,r2r1,s2s1, (z1,z2)НовМ, (w1,w2)НовМ
<лог.выр.>t2(<P>p1<лог.-список>p2,t1)
p2p1,t2t1
<лог.-список>p1,t2 =<P>q1 {Равноp2,q2,t1}
p2p1,q2q1, (t1,t2)Нов
<лог.-список>p1,t2#<P>q1{Не равноp2,q2,t1}
p2 p1, q2 q1, (t1, t2) Нов
Множества выбора для L-атрибутной грамматики
¶ - концевой маркер
Найти аннулирующие нетерминалы и правила:
Вычеркивание правил, содержащих терминальные символы:
<S><совок.операторов>
<совок.операторов> <оператор> <совок.операторов>
<совок.операторов> !
<оператор> <оператор присваивания>
<оператор> <условный оператор>
<оператор> <оператор цикла>
<оператор присваивания>Id= <E>;<E><T><E-список>
<E-список>+<T><E-список><E-список> !
<T> <F><T-список>
<T-список>*<F><T-список><T-список> !
<F> <P><F-список>
<F-список>^<P><F-список><F-список> !
<P>Id<P>Con<условный оператор>if<лог.выр.>then<оператор> <else-часть><else-часть>else <оператор><else-часть>!
<оператор цикла>while<лог.выр.> <совок.операторов>end_while<лог.выр.>(<P> <лог.спис.>)<лог.спис.>= <P><лог.спис.># <P>
Список аннулирующих нетерминальных грамматик:
<совок.операторов>
<E-список>
<T-список>
<F-список>
<else-часть>
Дополнение списка:
<S>
Полный список аннулирующих правил: 1,3,10,13,16,21
Построение отношения Начинается-Прямо-С:
Вычисление отношения Начинается-С:
Вычисление множества Первдля каждого нетерминала:
Перв(<S>) = {Id, if, while}
Перв(<совок.операторов>) = { Id,if,while}
Перв(<оператор>) = { Id,if,while}
Перв(<оператор присваивания>) = {Id}
Перв(<E>) = {Con,Id}
Перв(<E-список>) = { + }
Перв(<T>) = {Con,Id}
Перв(<T-список>) = { * }
Перв(<F>) = {Con,Id}
Перв(<F-список>) = { ^ }
Перв(<P>) = {Con,Id}
Перв(<условный оператор>) = {if}
Перв(<else-часть>) = {else}
Перв(<оператор цикла>) = {while}
Перв(<лог.выр.>) = { ( }
Перв(<лог.-список>) = {=, #}
Вычисление множества Первдля каждого правила:
Перв(<совок.операторов>) = { Id,if,while}
Перв(<оператор><совок.операторов>)= Перв(<оператор>) = { Id,if,while}
Перв( ! ) = { }
Перв(<оператор присваивания>) = {Id}
Перв(<условный оператор>) = {if}
Перв(<оператор цикла>) = {while}
Перв(Id= <E>;) = {Id}
Перв(<T><E-список>) = Перв(<T>) = {Con,Id}
Перв( +<T> <E-список>) = { + }
Перв( ! ) = { }
Перв(<F><T-список>) = Перв(<F>) = {Con,Id}
Перв( * <F> <T-список>) = { * }
Перв( ! ) = { }
Перв(<P><F-список>) = Перв(<P>) = {Con,Id}
Перв( ^ <P><F-список>) = { ^ }
Перв( ! ) = { }
Перв(Id) = {Id}
Перв(Con) = {Con}
Перв(if<лог.выр.>then<оператор><else-часть>) = {if}
Перв(else<оператор> ) = {else}
Перв( ! ) = { }
Перв(while<лог.выр.><совокупность операторов>end_while) = {while}
Перв( (<P><лог.-список>) ) = { ( }
Перв( =<P>) = { = }
Перв( #<P>) = { # }
Построение отношения Прямо-Перед:
Построение отношения Прямо-На-Конце:
Вычисление отношения На-Конце:
Вычисление отношения Перед= (На-Конце*Прямо-Перед) *Начинается-С.
Расширение отношения Передпутем включения концевого маркера.
Вычисление множества След для каждого аннулирующего нетерминала:
След(<S>) = {¶}
След(<совок.операторов>) = { end_while,¶}
След(<E-список>) = { ; }
След(<T-список>) = { + , ; }
След(<F-список>) = { *, +, ; }
След(<else-часть>) = { Id, if, while, else, end_while, ¶ }
Вычисление множества Выбора:
Перв(<совок.операторов>) + След(<S>) = {Id,if,while,¶}
Перв(<оператор><совок.операторов>)= Перв(<оператор>) = { Id,if,while}
Перв( ! ) + След(<совок.операторов>) = { end_while,¶}
Перв(<оператор присваивания>) = {Id}
Перв(<условный оператор>) = {if}
Перв(<оператор цикла>) = {while}
Перв(Id= <E>;) = {Id}
Перв(<T><E-список>) = Перв(<T>) = {Con,Id}
Перв( +<T> <E-список>) = { + }
Перв( ! ) + След(<E-список>) = { ; }
Перв(<F><T-список>) = Перв(<F>) = {Con,Id}
Перв( * <F> <T-список>) = { * }
Перв( ! ) + След(<T-список>) = { + , ; }
Перв(<P><F-список>) = Перв(<P>) = {Con,Id}
Перв( ^ <P><F-список>) = { ^ }
Перв( ! ) + След(<F-список>) = { *, +, ; }
Перв(Id) = {Id}
Перв(Con) = {Con}
Перв(if<лог.выр.>then<оператор><else-часть>) = {if}
Перв(else<оператор> ) = {else}
Перв( ! ) + След(<else-часть>) = { Id, if, while, else, end_while, ¶ }
Перв(while<лог.выр.><совокупность операторов>end_while) = { while }
Перв( (<P><лог.-список>) ) = { ( }
Перв( =<P>) = { = }
Перв( #<P>) = { # }
//Вообще говоря, множество выбора правил 20 и 21 пересекаются, но прога работает. =)
Управляющая таблица МП-автомата транслирующей грамматики
|
Con |
Id |
if |
while |
else |
# |
= |
^ |
* |
+ |
; |
( |
) |
then |
end_while |
¶ |
<S> |
|
#1 |
#1 |
#1 |
|
|
|
|
|
|
|
|
|
|
|
#1 |
<совокупность операторов> |
|
#2 |
#2 |
#2 |
|
|
|
|
|
|
|
|
|
|
#3 |
#3 |
<оператор> |
|
#4 |
#5 |
#6 |
|
|
|
|
|
|
|
|
|
|
|
|
<оператор присваивания> |
|
#7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<E> |
#8 |
#8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<E-список> |
|
|
|
|
|
|
|
|
|
#9 |
#10 |
|
|
|
|
|
<T> |
#11 |
#11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<T-список> |
|
|
|
|
|
|
|
|
#12 |
#13 |
#13 |
|
|
|
|
|
<F> |
#14 |
#14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<F-список> |
|
|
|
|
|
|
|
#15 |
#16 |
#16 |
#16 |
|
|
|
|
|
<P> |
#18 |
#17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<условный оператор> |
|
|
#19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
<else-часть> |
|
#21 |
#21 |
#21 |
#20 |
|
|
|
|
|
|
|
|
|
|
#21 |
<оператор цикла> |
|
|
|
#22 |
|
|
|
|
|
|
|
|
|
|
|
|
<логическое выражение> |
|
|
|
|
|
|
|
|
|
|
|
#23 |
|
|
|
|
<логический-список> |
|
|
|
|
|
#25 |
#24 |
|
|
|
|
|
|
|
|
|
= |
|
|
|
|
|
|
ВС |
|
|
|
|
|
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
|
ВС |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
ВС |
|
|
|
Then |
|
|
|
|
|
|
|
|
|
|
|
|
|
ВС |
|
|
end_while |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ВС |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Д |
{Присвоить} |
Выдать (Присвоить), Вытолкнуть, Держать | |||||||||||||||
{Сложить} |
Выдать (Сложить), Вытолкнуть, Держать | |||||||||||||||
{Умножить} |
Выдать (Умножить), Вытолкнуть, Держать | |||||||||||||||
{В степень} |
Выдать (В степень), Вытолкнуть, Держать | |||||||||||||||
{Переход по 0} |
Выдать (Переход по 0), Вытолкнуть, Держать | |||||||||||||||
{Безусловный переход} |
Выдать (Безусловный переход), Вытолкнуть, Держать | |||||||||||||||
{Метка} |
Выдать (Метка), Вытолкнуть, Держать | |||||||||||||||
{Переход по сравнению} |
Выдать (Переход по сравнению), Вытолкнуть, Держать | |||||||||||||||
{Равно} |
Выдать (Равно), Вытолкнуть, Держать | |||||||||||||||
{Не равно} |
Выдать (Не равно), Вытолкнуть, Держать |
Начальное содержимое автомата: <S>
#1 Заменить (<совокупность операторов>), Держать
#2 Заменить (<оператор><совокупность операторов>), Держать
#3 Вытолкнуть, Держать
#4 Заменить (<оператор присваивания>), Держать
#5 Заменить (<условный оператор>), Держать
#6 Заменить (<оператор цикла>), Держать
#7 Заменить (‘=’<E> {Присвоить}‘;’), Сдвиг
#8 Заменить (<T><E-список>), Держать
#9 Заменить (<T> {Сложить}<E-список>), Сдвиг
#10 Вытолкнуть, Держать
#11 Заменить (<F><T-список>), Держать
#12 Заменить (<F> {Умножить}<T-список>), Сдвиг
#13 Вытолкнуть, Держать
#14 Заменить (<P><F-список>), Держать
#15 Заменить (<P> {В степень}<F-список>), Сдвиг
#16 Вытолкнуть, Держать
#17 Вытолкнуть, Сдвиг
#18 Вытолкнуть, Сдвиг
#19 Заменить (<лог.выр.>{Переход по 0}then<оператор><else-часть>), Сдвиг
#20 Заменить ({Безусловный переход} {Метка}<оператор> {Метка}), Сдвиг
#21 Заменить ({Метка}), Держать
#22 Заменить ({Метка}<лог.выр.>{Переход по сравнению}<совокупность операторов>
{Безусловный переход} {Метка}end_while), Сдвиг
#23 Заменить (<P><логический-список>’)’), Сдвиг
#24 Заменить (<P>{Равно}), Сдвиг
#25 Заменить (<P>{Не равно}), Сдвиг
ВС Вытолкнуть, Сдвиг
Д Допустить
Пример замены магазинных символов, содержащих атрибутные поля:
Оператор цикла:
Текущая входная цепочка |
Содержание магазина | |
while (i # 10) |
1 |
<оператор цикла> |
i = i + 1; |
0 |
|
end_while¶ |
|
|
while (i # 10) |
14 |
While |
i = i + 1; |
13 |
{Метка} |
end_while¶ |
12 |
1 |
|
11 |
<логическое выражение> |
|
10 |
8 |
|
9 |
{Переход по сравнению} |
|
8 |
(-1) |
|
7 |
0 |
|
6 |
<совокупность операторов> |
|
5 |
{Безусловный переход} |
|
4 |
1 |
|
3 |
{Метка} |
|
2 |
0 |
|
1 |
end_while |
|
0 |
|
В массив меток добавляется два указателя на массив команд, а в магазин записываются адреса этих ячеек в массиве меток.
Условный оператор:
Текущая входная цепочка |
Содержание магазина | |
if(d=c)then |
1 |
<условный оператор> |
a=d*2; |
0 |
|
else a=d^3;¶ |
|
|
|
|
|
|
|
|
if(d=c)then |
10 |
If |
a=d*2; |
9 |
<логическое выражение> |
else a=d^3;¶ |
8 |
6 |
|
7 |
{Переход по 0} |
|
6 |
(-1) |
|
5 |
0 |
|
4 |
Then |
|
3 |
<оператор> |
|
2 |
<else-часть> |
|
1 |
0 |
|
0 |
|
Тестовый пример
Текст программы