Uploaded by い朝霧の深

Теория автоматов и формальных языков

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ
Брянский государственный технический университет
«УТВЕРЖДАЮ»
Первый проректор по учебной работе
____________ А.Н. Прокофьев
« » ____________ 2015г.
ТЕОРИЯ ВЫЧИСЛИТЕЛЬНЫХ ПРОЦЕССОВ И СТРУКТУР
АТРИБУТНЫЕ ТРАНСЛИРУЮЩИЕ ГРАММАТИКИ
Методические указания
к выполнению лабораторной работы №2
направление подготовки – 230100 «Информатика и вычислительная техника»
профиль – Программное обеспечение вычислительной техники
и автоматизированных систем
квалификация – бакалавр
форма обучения – очная
Брянск 2015
2
УКД 629.42.02/.06(07)+621.313.2(07)
Теория вычислительных процессов и структур. Атрибутные
транслирующие грамматики: методические указания к выполнению
лабораторной работы №2. Направление подготовки: 230100
Информатика и вычислительная техника. Для студентов очной формы
обучения. Профиль: «Программное обеспечение вычислительной
техники и автоматизированных систем». – Брянск: ФГБОУ ВПО
БГТУ, 2015. – 20 с.
Разработали:
А.Н.Горбунов
доцент, канд. техн. наук,
Я.И.Сиваков
старший преподаватель
Рекомендовано кафедрой «Информатика и программное
обеспечение» БГТУ (протокол № от __.__.2015 г.)
3
1. ЦЕЛЬ РАБОТЫ
Целью работы является получение практических навыков по
составлению правил атрибутной транслирующей грамматики и
проверка их правильности путем моделирования.
Продолжительность работы – 6 часов.
2. ОСНОВНЫЕ ПОНЯТИЯ И ТЕРМИНЫ
Транслирующие грамматики позволяют задавать соответствия
между цепочками входного и выходного языков, называемые
переводом. Эти соответствия отражают структурные или
синтаксические свойства входных и выходных цепочек, однако при
попытках их использования для описания контекстно-зависимых
условий или смысла конструкций – семантики языков
программирования возникают значительные трудности. Поэтому для
задания семантики применяются различные приемы: W -грамматики,
венский метаязык, аксиоматический и денотационный методы, а
также атрибутные транслирующие грамматики.
Существует два вида записи для связанных с продукциями
семантических правил — синтаксически управляемые определения и
схемы трансляции. Синтаксически управляемые определения
представляют собой высокоуровневые спецификации трансляции,
скрывающие множество деталей реализации и освобождающие
пользователя от явного указания порядка выполнения трансляции.
Схемы трансляции указывают порядок, в котором выполняются
семантические правила; так что эти схемы показывают определенную
часть деталей реализации. Выполнение семантических правил может
генерировать код, сохранять информацию в таблице символов,
выводить сообщения об ошибках или выполнять какие-либо другие
действия.
Синтаксически управляемое определение представляет собой
обобщение контекстно-свободной грамматики, в которой каждый
грамматический символ имеет связанное множество атрибутов,
разделенное на два подмножества, — синтезируемые и наследуемые
атрибуты этого грамматического символа. Если рассматривать узел
4
грамматического символа в дереве разбора как запись с полями для
хранения информации, то атрибут соответствует имени поля.
Атрибутные транслирующие грамматики (АТ-грамматики)
отличаются от транслирующих грамматик тем, что символам
грамматики приписываются атрибуты, отражающие семантическую
информацию, а правилам грамматики сопоставляются правила
вычисления значений атрибутов. Атрибут может представлять собой
все, что угодно, — строку, число, тип, адрес памяти и т.д. Значение
атрибута в узле дерева разбора определяется семантическими
правилами, связанными с используемой в данном узле продукцией.
Значение синтезируемого атрибута в узле вычисляется по значениям
атрибутов в дочерних по отношению к данному узлах; значения
наследуемых атрибутов определяются значениями атрибутов соседних
(т.е. узлов, дочерних по отношению к родительскому узлу данного
узла) и родительского узлов.
Семантические правила определяют зависимости между
атрибутами, которые представляются графом зависимости,
определяющим порядок выполнения семантических правил, что в
свою очередь дает значения атрибутов в узлах дерева разбора
входной строки. Семантические правила могут иметь и побочные
действия, например вывод значения или изменение глобальной
переменной. Дерево разбора, показывающее значения атрибутов в
каждом узле, называется аннотированным, а процесс вычисления
значений атрибутов в узлах дерева — аннотированием дерева
разбора.
2.1 Синтезируемые атрибуты.
В синтаксически управляемом определении каждая продукция
грамматики А → а имеет связанное с ней множество семантических
правил вида b := f (c1, c2, …, ск), где f — функция, с1, с2, ..., ск —
атрибуты грамматических символов продукции, а b —
синтезируемый атрибут символа А или наследуемый атрибут одного
из грамматических символов правой части продукции.
В любом случае атрибут b зависит от атрибутов с1 с2, ..., ск.
Таким образом, атрибутная грамматика является синтаксически
управляемым определением, в котором функции в семантических
5
правилах не имеют побочных эффектов. Функции в семантических
правилах зачастую записываются как выражения. Может быть так, что
единственная цель семантического правила в синтаксически
управляемом определении состоит именно в создании побочного
эффекта. Такие семантические правила записываются как вызовы
процедур или фрагменты программ. Их можно рассматривать как
правила, определяющие значения фиктивных синтезируемых
атрибутов нетерминала в левой части связанной продукции;
фиктивный атрибут и знак присвоения : = при этом не указываются.
В качестве примера рассмотрим синтаксически управляемое
определение программы простого калькулятора. Это определение
связывает с каждым из нетерминалов Е, Т и F целочисленный
синтезируемый атрибут val. Для каждой Е-, Т- и F -продукции
семантическое правило вычисляет значение атрибута val нетерминала
из левой части продукции по значениям атрибутов нетерминалов
правой части.
Продукция
Семантические правила
L→En
print(E.val)
E→E1+ Т
E.val := E1.val + T.val
Е→Т
E.val := T.val
T→T1*F
T.val :=T 1 .val * F.val
T→F
T.val := F.val
F→ (E)
F.val := E.val
F→ digit
F.val := digit.lexval
Лексема digit имеет синтезируемый атрибут lexval, значение
которого предоставляется лексическим анализатором. Правило,
связанное с продукцией L → Еn для стартового нетерминала L,
представляет собой процедуру вывода значения арифметического
выражения, порождаемого E (это правило можно рассматривать как
определяющее фиктивный атрибут для нетерминала L).
В синтаксически управляемом определении предполагается,
что терминалы могут иметь только синтезируемые атрибуты,
поскольку определение не дает никаких семантических правил для
терминалов
(обычно
значения
атрибутов
терминалов
предоставляются лексическим анализатором). Кроме того, если иное
не оговорено особо, стартовый символ не имеет наследуемых
атрибутов.
6
Синтаксически управляемое определение, использующее только
синтезируемые атрибуты, называется S-атрибутным определением.
S-атрибутное определение в рассматриваемом примере описывает
калькулятор, считывающий арифметическое выражение из цифр,
скобок, операторов + и *, за которым следует символ новой строки n,
и выводит значение выражения. Например, получив выражение
3*5+4, за которым следует символ новой строки, программа выводит
значение 19. На рис. 2.1 показано аннотированное дерево разбора для
входной строки 3*5+4n. Выход программы, печатаемый в корне
дерева, представляет собой значение E.val в первом дочернем узле
корня дерева.
L
n
E.val=19
+
T.val = 3
F.val=3
E.val:= 15
T.val=4
T.val =15
F.val = 4
*
digit./ewa/ = 4
F.val=5
digit.lexval=5
digit.lexval= 3
Рис. 2.1. Аннотированное дерево разбора для 3*5+4n.
Рассмотрим узел продукции T→T*F. Значение атрибута T.val в
этом узле определяется следующим образом:
Продукция Семантическое правило
Т→Т1 * F
T.val := T1.val * F.val
При использовании этого семантического правила в данном узле
T1.val имеет значение 3, полученное от левого наследника, a F.val —
значение 5, полученное от правого наследника. Следовательно, в этом
узле T.val составляет 15.
Правило, связанное с продукцией для стартового нетерминала
L → Еn, выводит значение выражения, порожденного Е.
7
2.2. Наследуемые атрибуты.
Наследуемые атрибуты представляют собой атрибуты, значения
которых в узле дерева разбора определяются атрибутами родительского
и/или дочерних по отношению к родительскому узлов. Наследуемые
атрибуты удобны для выражения зависимости конструкций языка
программирования от контекста, в котором они появляются. Например,
мы можем использовать наследуемые атрибуты для отслеживания,
появляется ли идентификатор слева или справа от знака присвоения,
чтобы определить, потребуется ли адрес или значение данного
идентификатора. Хотя всегда можно переписать синтаксически
управляемое определение таким образом, чтобы использовать только
синтезируемые атрибуты, зачастую более естественно воспользоваться
синтаксически
управляемым
определением
с
наследуемыми
атрибутами.
Рассмотрим пример, в котором наследуемый атрибут
распространяет информацию о типе на различные идентификаторы в
объявлении.
Пусть объявление, порождаемое нетерминалом D в
синтаксически управляемом определении, приведенном ниже,
состоит из ключевых слов int или real, за которыми следует список
идентификаторов. Нетерминал Т имеет синтезируемый атрибут type,
значение которого определяется ключевым словом объявления.
Семантическое правило L.in := Т.type, связанное с продукцией
D → ТL, определяет наследуемый атрибут L.in как тип объявления.
Затем приведенные правила распространяют этот тип вниз по дереву
разбора с использованием атрибута L.in. Правила, связанные с
продукциями для L, вызывают процедуру addtype для добавления
типа каждого идентификатора к его записи в таблице символов
(определяемой атрибутом entry).
Продукция
Семантические правила
D → TL
L.in:= Т.type
T → int
Т.type:= integer
T → reaI
T.type := real
L → L 1 , id
L1.in := L.in
addtype(id. entry, L.in)
L → id
addtype(id.entry, L.in)
8
На рис. 2.2 приведено аннотированное дерево разбора для
предложения real id1, id2, id3.
D
T.type = real
L.in = real
real
L.in = real
L.in = real
,
,
id3
id2
id1
Рис. 2.2 Дерево разбора с наследуемыми атрибутами in в каждом узле,
помеченном L.
3. ОПИСАНИЕ И ВВОД ГРАММАТИКИ
В комплект программы входит текстовый редактор, с помощью
которого можно вводить грамматику. Для входа в редактор перейдите
в папку программы и запустите файл SAG  ScilicetEditor 
ScilicetEditor.exe. Этот редактор настроен на автоматический запуск
анализатора SAG. Так же он подсвечивает синтаксис вводимых
конструкций.
Рис. 1. Окно текстового редактора для ввода грамматики
9
Грамматика описывается при помощи нотации Бакуса-Наура.
Терминальные символы заключаются в кавычки. Терминальные и
нетерминальные символы могут состоять из нескольких литер.
Внутри многолитерных символов не должны встречаться
специальные символы, в том числе и пробелы. Правила грамматики
записывается в виде
нетерминальный_символ = цепочка
Каждое определение нетерминального символа должно
заканчиваться знаком точки с запятой (;).
Между символами =, а также между нетерминальными
символами допускается любое число пробелов. Описание грамматики
должно начинаться с правила, определяющего начальный символ
(аксиому) грамматики. В тексте описания грамматики можно
использовать комментарии. Комментарий начинается с двух слешей
(//) и продолжается до конца строки.
В терминальных символах можно использовать следующие
обозначения:
\r – перевод каретки (символ с кодом 10);
\n – возврат каретки (символ с кодом 13);
\t – знак табуляции;
\\ – знак обратного слеша;
\’ – одинарная кавычка;
\” – двойная кавычка.
Атрибутные правила записываются внутри фигурных скобок и
разделяются точками с запятой (;). Внутри атрибутных правил
обращения к атрибутам записываются в виде
нетерминальный_символ . название_атрибута
Сами атрибутные правила должны выглядеть так:
атрибут = выражение_с_атрибутами
В выражениях допустимо использовать математические
операции «+», «–» , «*» , «/» и операцию объединения строк «&».
Кроме того, ко всем успешно разобранным нетерминальным
символам сразу после их разбора анализатор добавляет атрибут text, в
10
который помещает ту часть исходной цепочки, которая соответствует
рассматриваемому нетерминальному символу. Этот атрибут в дереве
разбора скрыт (какая часть цепочки соответствуем нетерминальному
символу легко узнать, выполнив щелчок левой кнопкой мыши по узлу
дерева).
К названиям нетерминальных символов допустимо приписывать
числовой суффикс для различения этих символов в атрибутных
правилах. Это требуется, если один и тот же нетерминальный символ
встречается в правиле более одного раза и есть атрибутное правило,
ссылающееся на него (см. листинг 1, правило 4).
Пустые
цепочки
следует
задавать
предопределённым
нетерминальным символом _EMPTY. Для упрощения задания
непустых
буквенно-цифровых
последовательностей
можно
применять встроенный нетерминальный символ _TEXT.
Рассмотрим пример грамматики для распознавания объявлений
переменных в стиле языка Си с сохранением типов данных для
каждой переменной. Пример такой грамматики показан в листинге 1.
Листинг 1. Пример грамматики.
[1]
[2]
VarBlock = VarRule VarBlock;
VarBlock = _EMPTY;
[3]
VarRule = Type
{ Var.type = Type.text;
VarList.type = Type.text }
' ' Var VarList ';' SPACE;
[4]
[5]
VarList = { Var.type = VarList.type;
VarList2.type = VarList.type }
',' SPACE Var VarList2;
VarList = _EMPTY;
[6]
[7]
[8]
Type = _TEXT;
Var = _TEXT;
Number = _TEXT;
[9] SPACE = ' ';
[10] SPACE = '\n';
11
[11] SPACE = _EMPTY;
После того как грамматика набрана, она должна быть сохранена.
Имя файла выбирается произвольно, расширение должно быть lat.
4. ПРОВЕРКА И ТРАНСЛЯЦИЯ
НАБРАННОЙ ГРАММАТИКИ
4.1. Проверка синтаксиса грамматики
После того как файл с грамматикой создан и сохранен на диске,
можно проверить его на соответствие правилам записи БНФ. Для
проверки синтаксиса и трансляции в редакторе есть две кнопки на
панели инструментов (рис.2).
Рис. 2. Кнопки на панели для работы с грамматикой
Кнопка проверить синтаксис позволяет проанализировать
набранную грамматику и обнаружить строки, не соответствующие
правилам формального описания. Вся отладочная информация
выводится в окно статуса, находящееся в нижней части редактора
(рис.3).
12
Рис. 3. Окно статуса при успешной проверке
На рис. 3 показан случай, когда набранная вами грамматика
соответствует всем правилам БНФ и может быть откомпилирована и
использована в дальнейшем для разбора цепочек. Если же цепочка не
соответствует правилам, то в этом окошке можно посмотреть
информацию об ошибке. Так, если в грамматику ввести ошибочное
правило (например, использовать специальные символы)
Var&Block = VarRule VarBlock;
то можно увидеть сообщение об ошибке, показанное на рис.4.
Рис. 4. Окно статуса с ошибкой
При этом будет указана строка в файле грамматики и символ,
который вызвал ошибку. В указанном примере ошибочным является
правило, набранное в первой строке, четвертом символе.
4.2.
Трансляция грамматики и запуск SAG
Если введенная грамматика не содержит ошибок (при проверке
синтаксиса вы видите окно статуса, похожее на то, что изображено на
рис. 4), то можно компилировать и запускать саму программу SAG.
Для этого необходимо, установив указатель мыши на кнопке запуска
13
на панели инструментов (кнопка в виде зеленого треугольника  рис.
3), нажать левую клавишу мыши.
После этого должно открыться окно программы, в котором
можно вводить цепочки для разбора по введенной вами грамматике.
SAG также позволяет просматривать словари нетерминальных и
терминальных символов. Для этого достаточно воспользоваться
кнопкам VN и VT соответственно. Окно программы с открытым
словарем нетерминальных символов показано на рис.5.
Рис. 5. Словарь нетерминальных символов
5. РАЗБОР ЦЕПОЧЕК
ПО СОЗДАННОЙ ГРАММАТИКЕ
Окно SAG (рис. 6) состоит из двух главных полей: левое поле –
дерево разбора, правое – разбираемая цепочка.
Цепочку можно вводить в правое окно, используя клавиатуру,
или открыть какой-нибудь текстовый файл, содержащий ее. Для
14
загрузки цепочки из файла используется пункт меню Файл 
Открыть.
При вводе цепочки в правое окно в левом производится ее
разбор по созданной грамматике и построение дерева. Если цепочка
не соответствует грамматике, в левом окне появляется надпись
«цепочка не распознана» (рис.6).
Рис. 6. Анализ ошибочной цепочки
После ввода цепочки, которая соответствует вашей грамматике,
в левом окне можно посмотреть дерево разбора и конкретные
нетерминальные
символы,
соответствующие
конструкциям
грамматики. Кроме того, для каждого нетерминального символа
показаны соответствующие ему атрибуты. При выделении некоторого
элемента дерева разбора в левой панели справа выделяется
соответствующая ему часть цепочки.
Рассмотрим пример разбора строки, приведенной в листинге 2
(разбор производится по грамматике, представленной в листинге 1).
Листинг 2. Строка для разбора.
int a,b;
float c,d;
15
После ввода этой строки в правую панель слева будет построено
дерево разбора (рис. 7). На верхнем уровне дерева находится
нетерминальный
символ
VarBlock,
соответствующий
всей
рассматриваемой цепочке. Видно, что для каждого нетерминального
символа Var, обозначающего имя переменной в программе-цепочке
анализатор создал атрибут type, в котором сохранил тип переменной.
Рис. 7. Дерево разбора
Задания
1. Расширить заданную грамматику, задающую математическое
выражение со скобками и операциями "+", "-", "*", "/" до атрибутной,
подсчитывающей значение выражения.
Правила исходной грамматики:
exp = mulDiv '+' exp;
exp = mulDiv '-' exp;
exp = mulDiv;
mulDiv = groupOrNumber '*' mulDiv;
mulDiv = groupOrNumber '/' mulDiv;
16
mulDiv = groupOrNumber;
groupOrNumber = '(' exp ')';
groupOrNumber = _TEXT;
2. Написать атрибутную грамматику, описывающую объявление
переменных как в языке Си. Для каждой переменной сохранить её
значение в атрибуте.
Так, если есть цепочка
int a = 10;
char *b = “abc”;
То при распознавании в дереве разбора должны встретиться два
узла, например, следующего вида:
VAR_DEF [ name=”a”; val = “10” ]
VAR_DEF [ name=”b”; val = “abc” ]
3. Усовершенствовать сделанную в п.2 грамматику так, чтобы
стартовый символ содержал атрибут, в котором был бы сохранён
список названий всех переменных.
Т.е. если есть цепочка
int a, b;
char *c, *s;
То корень дерева должен содержать атрибут
[ vars=”a b c s” ].
4. Усовершенствовать сделанную в п.3 грамматику так, чтобы можно
было задавать значения по-умолчанию для переменных. Т.е. в
случаях, когда значение явным образом не присвоено – задавать его
равным некой константе (которая должна задаваться через
наследуемый атрибут для стартового символа грамматики).
Так, если есть цепочка
char *s;
float f;
То при распознавании в дереве разбора должны встретиться
узлы, например, следующего вида:
VAR_DEF [ name=”s”; val = “NULL” ]
VAR_DEF [ name=”f”; val = “0.0” ]
17
(Здесь “NULL” – значение по-умолчанию для переменных типа
char*, a “0.0” – для переменных типа float).
5. Написать атрибутную грамматику, описывающую объявление
переменных как в языке Си или Паскаль (на выбор). Для каждой
переменной сохранить в атрибутах: название, тип данных и объём
занимаемой памяти. Грамматика должна поддерживать объявление
массивов.
Так, если есть цепочка
a[1..10]: array of integer;
b: real;
То при распознавании в дереве разбора должны встретиться два
узла, например, следующего вида:
VAR_DEF [ name=”a”; type=”array of integer”; memory=”40”]
VAR_DEF [ name=”b”; type=”real”; memory=”6”]
(Здесь предполагается, что под переменную типа integer
отводится 4 байта памяти.)
6. ПОДГОТОВКА К ЛАБОРАТОРНОЙ РАБОТЕ
В процессе подготовки к лабораторной работе студент должен
изучить соответствующие главы курса, после чего необходимо
построить для заданного языка грамматику. Для этого он должен:
1. Выписать несколько примеров цепочек, принадлежащих
заданному языку.
2. Проанализировать структуру выделенных цепочек – выделить
в них начало, конец, повторяющиеся части и символы.
3. Выделить простейшие структуры, обозначая структурные
части с помощью вводимых нетерминальных символов.
4. Для каждой из выделенных структурных частей построить
правила грамматики.
5. Объединить все правила в грамматику.
7. ПОРЯДОК ВЫПОЛНЕНИЯ РАБОТЫ
В процессе
необходимо:
выполнения
лабораторной
работы
студенту
18
1. Используя текстовый редактор создать файл с грамматикой.
2. Проверить грамматику на соответствие формальным правилам
описания и транслировать ее.
3. Запустить SAG и выполнить разборы цепочек. Определить,
принадлежат ли выбранные цепочки языку. Порожденные
цепочки записать в файл, используя команду Сохранить.
4. Если получены цепочки, которые не принадлежат языку, то
необходимо изменить грамматику и повторить вывод цепочек.
5. По окончании лабораторной работы файлы с грамматикой и
выведенными цепочками необходимо сохранить в архиве.
8. СОДЕРЖАНИЕ ОТЧЕТА
Отчет студента о проделанной работе должен содержать
следующие части:
1. Задание, определяющее входной язык.
2. Правила входной грамматики, записанные в форме БэкусаНаура.
3. Нетерминальный и терминальный словари, а также описание
множественных терминалов.
4. Примеры входных цепочек, полученных в результате левого и
правого выводов, деревья их вывода.
9. ЗАЩИТА ЛАБОРАТОРНОЙ РАБОТЫ
Для защиты лабораторной работы студенту необходимо знать:
1. Определение грамматики, вывода и языка.
2. Типы грамматик.
3. Понятия левого и правого вывода, дерева вывода и
неоднозначной грамматики.
На защите студент должен уметь объяснить, какой язык
порождает составленная им грамматика, какие ограничения
накладываются на язык, а также уметь строить простейшие
грамматики.
19
10. КОНТРОЛЬНЫЕ ВОПРОСЫ
Что называется алфавитом?
Что называется цепочкой?
Какими параметрами определяется формальная грамматика?
Какая грамматика называется контекстно-свободной?
Что называется языком грамматики?
Какой символ называется терминальным, а какой –
нетерминальным?
7. Какой символ называется аннулирующим?
8. Какой вывод называется правым, а какой – левым?
9. Какие символы называются непроизводящими?
10. Какие символы называются недостижимыми?
1.
2.
3.
4.
5.
6.
20
Теория языков программирования и методы трансляции.
Построение и анализ грамматики: методические указания к
выполнению лабораторной работы №1 для студентов очной формы
обучения специальности 230105 – «Программное обеспечение
вычислительной техники и автоматизированных систем»
ГОРБУНОВ АЛЕКСАНДР НИКОЛАЕВИЧ
СИВАКОВ ЯРОСЛАВ ИГОРЕВИЧ
Научный редактор В.К. Гулаков
Редактор издательства Л.И. Афонина
Компьютерный набор М.В. Березина
Темплан 2011г., п______
Подписано в печать __.__.07. Формат …..
Бумага офсетная. Офсетная
печать. Усл.печ.л _____. Уч.-изд.л _____ Тираж 30 экз.
Заказ_____
Бесплатно____
Брянский государственный технический университет.
241035, Брянск, бульвар 50-летия Октября, 7, БГТУ. 58-82-49.
Лаборатория оперативной полиграфии БГТУ, ул. Институтская, 16.
Download