You are on page 1of 29

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ

РОССИЙСКОЙ ФЕДЕРАЦИИ

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Московский государственный институт электроники и математики


(технический университет)

Кафедра “Информационные технологии


в автоматизированных системах”

ЛИНГВИСТИЧЕСКОЕ ОБЕСПЕЧЕНИЕ САПР

Методические указания к лабораторным работам

Москва 2007
Составитель: докт. техн. наук, проф. Л.В. Зайцева
канд. техн. наук, доц. Э.С. Клышинский
канд. физ.-мат. наук С.В. Ёлкин

Излагаются основные теоретические сведения, необходимые для


выполнения лабораторной работы по дисциплине “Программное и
лингвистическое обеспечение САПР” (раздел “Лингвистическое обеспечение”), а
также даются варианты заданий на лабораторные работы.
Предназначены для студентов 3-го курса специальности 22.03.00 –
“Системы автоматизированного проектирования”.

УДК 517.95

Лингвистическое обеспечение САПР: Метод. указания к лабораторным


работам/ Моск. гос. ин-т электроники и математики; Сост.: Л.В. Зайцева, Э.С.
Клышинский, С.В. Ёлкин. М., 2007. 29 с.

Ил. 17. Библиогр.: 7 назв.

ISBN 5-904506-025-9
СОДЕРЖАНИЕ

1. ОБЗОР ПРОЦЕССА КОМПИЛЯЦИИ.....................................................................................4


2. ПРЕДВАРИТЕЛЬНЫЕ МАТЕМАТИЧЕСКИЕ СВЕДЕНИЯ.................................................5
3. КОНЕЧНЫЕ АВТОМАТЫ (КА)...............................................................................................7
3.1. Определение.........................................................................................................................7
3.2. Диаграмма состояний..........................................................................................................7
3.3. Представление КА с помощью матрицы переходов........................................................8
3.4. Варианты индивидуальных заданий..................................................................................9
4. ПОНЯТИЕ О СИНТАКСИЧЕСКИ УПРАВЛЯЕМОЙ ТРАНСЛЯЦИИ...............................11
4.1. Метод синтаксически управляемой трансляции............................................................11
4.2. Оптимизация кода..............................................................................................................13
4.3. Практические рекомендации по программированию....................................................14
4.4. Генерация оптимального кода..........................................................................................15
4.5. Варианты индивидуальных заданий................................................................................16
5. НЕДЕТЕРМИНИРОВАННЫЕ КОНЕЧНЫЕ АВТОМАТЫ (НКА).....................................20
5.1. Определение.......................................................................................................................20
5.2. Методы построения КА по НКА......................................................................................20
5.3. Построение детерминированного КА по регулярному выражению.............................21
5.4 Варианты заданий...............................................................................................................23
6. АВТОМАТЫ С МАГАЗИННОЙ ПАМЯТЬЮ (МП - АВТОМАТЫ)...................................24
6.1. Определение.......................................................................................................................24
6.2. Построение примитивного МП - автомата......................................................................24
6.3. Построение непримитивного МП-автомата, осуществляющего заданный перевод
..............................................................................................................................................................25
6.4. Варианты индивидуальных заданий................................................................................26
7. КОНТРОЛЬНЫЕ ВОПРОСЫ ПО КУРСУ.............................................................................27
8. ПРАВИЛА ВЫБОРА ВАРИАНТА ЗАДАНИЯ......................................................................28
9. БИБЛИОГРАФИЧЕСКИЙ СПИСОК......................................................................................28

3
1. ОБЗОР ПРОЦЕССА КОМПИЛЯЦИИ
Процесс компиляции состоит в том, что некоторый входной язык переводится
посредством компилятора в выходной язык. При этом сохраняется семантическая связь
между соответствующими конструкциями входного и выходного языков. Компилятор
включает в себя две фазы:
1) фаза анализа входного языка;
2) фаза синтеза выходного языка.
В задачу первой фазы входит распознавание предложения входного языка и выделение
основных элементов. Задачей второй фазы является построение предложения выходного
языка в соответствии с информацией, полученной на первой фазе, и правилами перевода. В
теории построения компиляторов задачу первой фазы делят на лексический и
синтаксический анализ, а вторую фазу называют генерацией кода.
Лексический анализ состоит в распознавании отдельных частей предложений входного
языка, таких как идентификаторы, константы, ключевые слова, знаки операций, разделители
и другие элементы входного языка. Лексический анализатор выдает информацию о входных
предложениях на более высоком уровне, в терминах входного языка (идентификатор, кон-
станта, разделитель и т.д.). Эта информация необходима для синтаксического анализа пред-
ложений входного языка. Использование лексического анализатора снижает трудоемкость
построения анализирующей части компилятора.
Генератор кода, основываясь на информации, полученной от синтаксического
анализатора, и руководствуясь правилами перевода, осуществляет построение выходных
предложений. Выходную информацию компилятора называют объектным кодом.
Различают одно- и многопроходную схему построения компилятора. В однопроходной
схеме все элементы компилятора работают совместно, основываясь на входной информации.
В многопроходных схемах фазы компиляции разделяются. Лексический анализатор,
выполнив анализ входной информации, строит промежуточный код. Затем по этому коду
осуществляет проход сначала синтаксический анализатор, а затем и генератор кода. При этом
фазы компилятора могут произвольным образом объединяться (за счет чего количество
проходов уменьшается). В других случаях наоборот, генератор кода может несколько раз
проходить по промежуточному коду, например, с целью оптимизации взаимосвязанных
конструкций.
Схема построения компилятора зависит от особенностей входного языка и требуемого
качества выходного кода. Не все языки позволяют эффективно использовать однопроходную
схему компиляции, однако большинство современных языков программирования, таких как
Паскаль и Си, допускают эффективную реализацию однопроходной схемы компиляции.
Помимо анализа и синтеза компилятор решает задачи распределения памяти и
диагностики ошибок. В свое время широкое распространение получила однопроходная схема
компиляции, обеспечивающая высокую скорость трансляции и неплохое качество кода.
Алгоритмы построения различных фаз компиляторов существенно зависят от типа
разбираемой грамматики. В теории формальных языков грамматика G определяется
упорядоченной четверкой (VN, VT, Р, Z), где VT – алфавит терминалов, VN – алфавит
нетерминалов, Р –конечный набор правил подстановки, Z – начальный символ грамматики
(ZVN). Язык, порождаемый грамматикой, представляет собой множество терминальных
цепочек, которые можно вывести из начального символа Z. Вид правил подстановки,
допустимых в Р, определяет тип грамматики. Наибольшее число формальных алгоритмов
разбора можно применить для контекстно-свободных (КС) грамматик и регулярных или
автоматных (А) грамматик.

4
2. ПРЕДВАРИТЕЛЬНЫЕ МАТЕМАТИЧЕСКИЕ СВЕДЕНИЯ
Для эффективного усвоения курса проектирования элементов компиляторов
необходимо владеть сведениями по теории формальных языков и теории графов. Здесь будет
уместно напомнить некоторые основные термины и положения этих теорий, используемые в
излагаемом материале. Множеством называется совокупность элементов, объединенных
каким-либо признаком. Множество может содержать конечное и бесконечное число
элементов. На множествах определен ряд операций:

Объединение AB

Пересечение AB

Разность AB

AB
Включение

Рис. 1. Графическое представление операций над множествами


Декартовым произведением двух множеств А и В называется множество, состоящее из
всевозможных пар элементов (а b), в которых первый элемент а принадлежит множеству А, а
элемент b множеству В.
Отношением R, определенным на множестве А, называется какое-либо подмножество
декартова произведения множества А само на себя. Запись aRb означает, что пара (а,b)
принадлежит отношению R.
Отношение R на множестве А называется:
• рефлексивным, если aRa для всех а из А;
• иррефлексивным, если aRa ни для одного а из А;
• симметричным, если aRb влечет bRa для всех а,b из А;
• транзитивным, если aRb и bRc влекут aRc для a, b и с из А.
Графом G=(А,R) называется множество А, с определенным на нем отношением R.
Элементы множества А принято называть вершинами графа, а дугами - элементы отношения
R.
Если отношение R симметрично, то говорят, что граф неориентированный. В
противном случае граф является ориентированным.
Говорят, что два графа G1 (A1, R1) и G2= (А2, R2) равны (или изоморфны), если
существует такое отображение f: A1 -> A2, что aR1b тогда и только тогда, когда f(a)R2f(b).
Путем в графе длины n называется последовательность вершин (a0, а1, а2... an) такая,
что для каждого 1 ≤ i ≤ n существует дуга, выходящая из вершины a0, и входящая в вершину
an.
Циклом в графе называется путь из вершины в саму вершину. Если существует путь из
вершины a в вершину b, то говорят, что b достижима, из a. Степенью по входу вершины
называется число дуг, входящих в данную вершину. Степенью по выходу называется число
дуг, выходящих из данной вершины. Деревом называется ациклический ориентированный
граф, обладающий следующими свойствами:
1) существует одна вершина, называемая корнем дерева, имеющая степень по входу
ноль;
2) все остальные вершины имеют степень по входу единица;

5
3) все вершины доступны из корня.
Вершины дерева, имеющие степень по выходу ноль, называются листьями.
Для представления деревьев существует множество способов. Большинство способов
основано на записи вершин дерева в определенном порядке, возможно с использованием
дополнительной информации.

Рис. 2. Дерево Т – ориентированный граф


Прямой порядок вершин в дереве задается применением следующего алгоритма,
начиная с корня.
Шаг 1. Шаг 1 применить к вершине a. Если а - лист, включить вершину в список. Если
нет, и ее прямые потомки – вершины a0, a1, a2... an, включить a в список и затем применить
Шаг 1 к вершинам a0, а1, а2... an в этом порядке.
1,2,3,4,5,6,7,8,9 - прямой порядок вершин дерева Т. (рис. 1).
Обратный порядок вершин получается аналогично, но если a не лист, применить Шаг 1
к вершинам a0, a1, a2...an в этом порядке, а затем включить в список вершину a.
3,4,2,7,8,9,6,5,1- обратный порядок вершин дерева Т (рис. 1).
Для задания информации об уровне вложенности вершин используют скобочное
представление. Открывающая скобка говорит о переходе на один уровень вниз по дереву, а
закрывающая – на уровень вверх. Добавление скобок в прямой порядок вершин задает левое
скобочное представление, а в обратный - правое.
Для дерева Т (рис. 1):
1(2(3, 4), 5(6(7, 8, 9))) - левое скобочное представление;
((3, 4)2, ((7, 8, 9)6)5)1 - правое скобочное представление.
Для представления графов используются две распространенные схемы в виде списка и
в виде матрицы смежностей.
Перечисление всех дуг графа множеством пар вершин задает представление графа в
виде списка.
В качестве матрицы смежностей применяют булеву матрицу размером п×п, где n
число вершин графа. Элемент bij равен единице, если существует дуга (i,j), и нулю в
противном случае.
1 2 3 4 5 6 7 8 9
1 1 1
2 1 1
3
4
5 1
6 1 1 1
7
8
9
Рис. 3. Представление дерева Т в виде матрицы смежностей

6
3. КОНЕЧНЫЕ АВТОМАТЫ (КА)
Лексику большинства языков программирования и проблемно-ориентированных языков
можно описать регулярной грамматикой, правила которой имеют вид:
U::=N | WN, где NVT, U,WVN.
Для разбора предложения такой грамматики применяют конечные автоматы.

3.1. Определение
Детерминированным конечным автоматом называется пятерка (К, VT, M, S, Z), где
1) К – алфавит элементов, называемых состояниями;
2) VT – алфавит, называемый входным алфавитом (литеры, которые могут встретиться
в цепочке или предложении);
3) М – отображение (или функция) множества К×VТ во множество К (если M(Q,,T)=R,
то это означает, что из состояния Q при входной литере Т происходит переключение в
состояние R);
4) S  К – начальное состояние;
5) Z – непустое множество заключительных состояний, каждое из которых
принадлежит К.

3.2. Диаграмма состояний


Для визуализации регулярных грамматик и работы конечных автоматов часто
используются диаграммы состояний. Диаграмма состояний состоит из узлов, которые
соответствуют нетерминалам грамматики и состояниям автомата, и дуг, которые помечаются
терминалами и соединяют нетерминалы или состояния. Дуга из S1 в S2 существует тогда,
когда по соответствующему ей терминалу есть порождающее правило вида S2::= S1
терминал для левосторонней грамматики или S1::= терминал S2 для правосторонней
грамматики, а также переход автомата из состояния S1 в S2. При этом для правосторонней
грамматики, если начальная вершина, если она не имеет входящих дуг, то она опускается. В
противном случае генерируется правило вида S2::= S1 терминал | терминал. Аналогичное
правило действует для левосторонней грамматики для конечных символов.
Пример для грамматики:

S ::= 1U | 0V Z ::= U0 | V1
U ::= 0Z | 0 U ::= Z1 | 1
V ::= 1Z | 1 V ::= Z0 | 0
Z ::= 1U | 0V

Рис. 4. Грамматика и диаграмма состояний

Используя диаграмму состояний, можно легко распознать принадлежность цепочки


грамматике, задаваемой диаграммой. Делается это следующим образом.
1. Первым текущим состоянием считать начальное состояние S. Начать с самой левой
литеры в цепочке x и повторять шаг 2 до тех пор, пока не будет достигнут правый конец x.
2. Сканировать следующую литеру х, продвинуться по дуге, помеченной этой литерой,
переходя к следующему текущему состоянию.
Если на каком-то повторении шага 2 такой дуги не оказывается, то цепочка х не
является предложением языка. Если достигнут конец х, то x - предложение языка тогда и
только тогда, когда последнее текущее состояние является заключительным состоянием
грамматики.

7
3.3. Представление КА с помощью матрицы переходов
Метод ролей
Представление конечного автомата в виде пятерки множеств затруднительно для
восприятия, поэтому используют более наглядное представление в виде матрицы переходов.
Число столбцов этой матрицы определяется числом литер входного алфавита, а количество
строк -числом переходов. Строки, соответствующие состояния которых являются
заключительными, помечаются слева единицами. Строка начального состояния является
первой в матрице. Например, автомат
KA=(K,VT,M,S,Z)
К={А,В}; VT={0,1};S=A; Z={A};
М(А,0)=А; М(А,1)=В;
М(В,0)=В; M(В,1)=А;
может быть представлен в виде матрицы переходов следующим образом:
0 1
A A B 1
B B A

При построении КА для анализа конструкций языка удобно применять метод ролей.
Сущность метода ролей лучше рассмотреть на конкретном примере. Пусть необходимо
построить конечный распознаватель конструкции языка Фортран, допустимой за ключевым
словом REAL.
На первом этапе необходимо построить типичную конструкцию языка, включающую
все допустимые элементы. Такой конструкцией может быть следующая:
REAL B(2,N,8),C;
На втором этапе следует определить используемые лексемы. Такими лексемами будут
идентификатор «v», числовая константа «с», запятая «,» и правая, левая скобка соответ-
ственно «(», «)».
На третьем этапе формулируют назначение всех лексем построенной конструкции и
присваивают им роли. Каждой роли присваивается номер, начиная со второго. Первая роль
резервируется и имеет специальное назначение.
В( 2, N,8 ),С
2 345654782
2 - имя переменной, описываемой как REAL;
3 - левая скобка;
4 - целое число, задающее размерность;
5 - запятая, разделяющая размерности;
6 - идентификатор переменной, задающей переменную размерность;
7 - правая скобка;
8 - запятая, разделяющая переменные, определяемые как вещественные.
После того как роли определены, можно приступить к построению автомата по
следующему алгоритму.
1. Ввести начальное состояние и состояние ошибки.
2. Ввести состояния для каждой роли.
3. Построить таблицу переходов с числом строк, равным числу состояний, и числом
столбцов, равным количеству лексем. Поместить в таблицу переходы из одного состояния в
другое, если соответствующие роли могут следовать друг за другом.
4. Пополнить таблицу переходами в состояние ошибки.
5. Выбрать в качестве допускающих те состояния, роли которых появляются в конце
допустимой цепочки.
Для предлагаемого примера на первом шаге вводится начальное состояние 1 и
состояние - ошибки E. На втором шаге вводятся состояния 2-8, соответствующие ролям,
полученным на третьем этапе. Затем на третьем шаге строится таблица переходов и

8
заполняется, исходя из следующих соображений. Первым символом каждой допустимой
цепочки должен быть идентификатор переменной, поэтому в таблицу заносится переход из
начального состояния в состояние 2 при переходе соответствующей лексемы. За вхождением
лексемы с ролью 2 может следовать либо лексема с ролью 3, либо 8, то есть левая скобка или
запятая, что и отражено в таблице. Дальнейшее заполнение таблицы не должно вызывать
затруднений. И в завершение, все оставшиеся пустыми ячейки заполняются переходами в
состояние Е. Наконец, на пятом шаге строки соответствующие 2 и 7 состоянию помечаются
как допускающие, что соответствует идентификатору переменной и правой скобке.
v c , ( )
1 2 E E E E
2 E E 8 3 E 1
3 6 4 E E E
4 E E 5 E 4
5 6 E E E E
6 E E 5 E 7
7 E E 8 E E 1
8 2 E E E E
E E E E E E
Рис. 5. КА для распознавания цепочки, следующей за ключевым словом REAL

Построенный автомат не обязательно будет наилучшим с точки зрения размера


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

3.4. Варианты индивидуальных заданий


I. Написать программу, строящую лево- и правостороннюю грамматику:
1) 0 1 2) 0 1 3) 0 1 4) 0 1
A B A 0 A B C 0 A B C 0 A B A 0
B B C 0 B C B 1 B D B 0 B D C 0
C C C 1 C C C 1 C C D 0 C C D 0
D D D 1 D D D 1

5) 0 1 6) 0 1 7) 0 1
A A B 1 A A D 1 A B C 1
B C D 0 B B D 0 B D A 0
C B A 1 C B A 1 C B B 1
D A B 0 D C B 0 D C D 0
Программа должна поддерживать смену нетерминалов в матрице конечного автомата.

II. Построить программу конечного распознавателя для заданного языка:


1) число "l" – четное и число "0" – нечетное;
2) между вхождениями единиц четное число "0";
3) число вхождений пары "00" нечетное;
4) за каждым вхождением пары "11" следует "0";
5) каждый третий символ - "1";
6) имеется по крайней мере одна "1".

III. Построить КА для распознавания цепочек и анализа ошибок, которые


1) состоят из арифметических выражений и не содержат скобок;

9
2) представляют собой идентификаторы целого типа в Фортране, начинающиеся с I, J,
K, L, M N;
3) могут следовать за словом INTEGER в Фортране;
4) являются вещественными константами в Бейсике;
5) представляют собой комментарии в Паскале.
Разработать и отладить программу.

Выбор варианта.
Первая группа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2
1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1

Вторая группа.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4
5 6 1 2 3 4 5 6 1 2 3 4 5 6 1 2
2 3. 4 5 1 2 3 4 5 1 2 3 4 5 1 2

10
4. ПОНЯТИЕ О СИНТАКСИЧЕСКИ УПРАВЛЯЕМОЙ ТРАНСЛЯЦИИ

4.1. Метод синтаксически управляемой трансляции


Синтаксический анализатор, просматривая предложения языка, строит дерево разбора.
В вершинах этого дерева расположены основные синтаксические конструкции предложений
языка, а дуги показывают связь этих конструкций. Так для оператора присваивания вида:
ABC= C-(A+13)*D;
будет построена лексическим анализатором следующая цепочка:
<id>1 = <id>2 - (<id>3 + <iconst>1) * <id>4. В данном случае id означает лексему
«идентификатор», тогда как iconst - «целочисленная константа». На этапе синтаксического
анализа построенная цепочка представляется деревом (рис. 3).

Рис. 6. Дерево синтаксического разбора для оператора присваивания


ABC= C-(A+13)*D;
Дерево, построенное синтаксическим анализатором, используется для того, чтобы
получить перевод входной программы в соответствующий машинный код. Иногда это бывает
непосредственно машинный код или ассемблер, а иногда некоторый промежуточный код, ис-
пользуемый в последующем на этапе оптимизации и кодогенерации. На практике процессы
построения синтаксического дерева и генерация кода происходят обычно одновременно, но в
учебных целях разделим их на отдельные этапы.
Существует несколько методов построения промежуточного или итогового кода по
синтаксическому дереву. Метод синтаксически управляемой трансляции является наиболее
простым и достаточно эффективным. В этом методе каждой вершине n ставится в
соответствие связанная с ней цепочка кода С(n). Код для вышестоящей вершины n строится
на основе кода, для ее непосредственных потомков. Процесс перевода идет снизу вверх, от
листьев к корню (обратный порядок вершин). В каждый момент времени код генерируемой
цепочки добавляется в конец выходного буфера. Фиксированные цепочки и фиксированный
порядок задаются целевой машиной, её системой команд и используемым для перевода
алгоритмом.
Для иллюстрации синтаксически управляемой трансляции удобно воспользоваться
задачей трансляции простых операторов присваивания для двухадресной ЭВМ, близкой по
архитектуре процессорам семейства Intel Pentium. При построении дерева арифметического
оператора существуют вершины четырех типов:
a) идентификаторы и константы (листья дерева);
b) унарные операторы, например, унарный минус;
c) бинарные арифметические операторы, такие как +, -, *, /, div;
d) оператор присваивания (корень дерева).

11
а) идентификатор b) унарный оператор с) бинарный оператор d) присваивание
Рис. 7. Типы внутренних вершин
Для любого арифметического оператора присваивания, включающего простые
операции, например, бинарные + и * можно построить дерево с одной вершиной (корнем)
типа d и листьями типа a. Остальные внутренние вершины будут только типов b и с, причем
большая часть будет типа с (рис. 3).
Следует иметь в виду, что в нашем простейшем генераторе кода каждый шаг
вычисления узла дерева разбора помещает результат в аккумулятор (регистр еах). В более
сложных кодогенераторах, применяющих изощренные стратегии оптимизации, результаты
вычислений могут распределяться по нескольким регистрам, например, переменные в разное
время жизни могут быть синонимами регистров ebx, eсх, edx, esi, edi и т.д.
Алгоритм синтаксически управляемой трансляции простых операторов присваива ния
Вход: Помеченное упорядоченное дерево, представляющее оператор присваивания,
включающий арифметические операции.
Выход: Код на языке ассемблера, вычисляющий этот оператор присваивания.
Метод: Обходить дерево рекурсивно снизу вверх, слева направо (обратный порядок
вершин), пока не будут обработаны все узлы дерева. Нужно отметить, что при выборе
другого порядка обхода дерева разбора – сверху вниз, справа налево – транслятор может
генерировать более короткие последовательности кода уже до этапа оптимизации. Выбор
стратегии обхода дерева оставляется разработчику.
1) Если n – лист дерева, помеченный некоторым идентификатором id или константой
iconst, то соответствующий код С(п) будет представлять собой цепочку:
mov eax ,id/iconst .
2) Если п – узел дерева, помеченный бинарной операцией, а его потомками являются
узлы l (левый) и r (правый), то кодом для С(п) будет:
код С(l)
push eax
код С(r)
pop edх
xchg еах, edx
ор еах, edx
Следует учесть, что каждая бинарная операция ор будет иметь свою форму и кодировку
последней строчки:
+ add еах, edx
- sub еах, edx
* imul еах. edx
/ (div) idiv еах, edx
Оператор xchg еах, edx меняет местами содержимое регистров еах и edx.
3) Если n – узел дерева, помеченный унарной операцией, а его единственный потомок –
узел m, то С(n) будет представляться последовательностью
код С(m)
op еах
Для унарного минуса (отрицание) последняя строчка записывается как
neg еах .
4) Если n – узел дерева, помеченный операцией присваивания, его правым потомком
является узел r, а левым – идентификатор id, то кодом для С(n) будет последовательность:
код С(r)
mov id,eax

12
Результат работы данного упрощенного алгоритма для примера представлен на рис. 5.
mov eax,C C
push eax
mov eax,A A
push eax
mov eax,13 13 A+13
pop edx
xchg eax,edx
add eax,edx
push eax (A+13)*D C-(A+13)*D
mov eax,D D
pop edx
xchg eax,edx
imul eax,edx
pop edx
xchg eax,edx
sub eax,edx
mov A, eax =
Рис. 8. Результат генерации кода

4.2. Оптимизация кода


Всегда желательно иметь транслятор, который генерирует код, занимающий
минимальное количество памяти и выполняющийся за минимальное время. В случае
применения синтаксически управляемой трансляции получаемый код является далеко не
оптимальным. В этом случае желательно применение оптимизации. Оптимизация состоит в
замене одной последовательности команд на эквивалентную ей, но выполняемую целевым
процессором за меньшее количество тактов работы процессора (оптимизация по скорости)
или кодируемую меньшим количеством байтов (оптимизация по размеру)
последовательность.
При проведении оптимизации следует учитывать факт, что операции сложения и
умножения являются коммутативными, и потому при необходимости для них возможна
перестановка операндов, тогда как для операций вычитания и деления этого делать нельзя.
Анализ сгенерированного на предыдущем шаге кода (рис. 5) позволяет сформировать
следующие предложения по оптимизации кода.
1) Цепочка вида
mov еах, id1/iconst1
push еах
С(а)
pop edx
xchg еах, edx
op еах. edx
при условии баланса операций push/pop может быть заменена на последовательность:
С(а)
mov edx, id1/iconst1
xchg еах, edx
op еах, edx
Оптимизация, подобная проводимой, возможна для некоммутативных операций
вычитания (sub), деления (idiv). Аналогичные манипуляции возможны и для коммутативных
операций сложения (add) и умножения (imul).
2) Цепочка вида
push еах
mov еах, id1/iconst1
pop edx

13
xchg eax, edx
sub eax, edx
может быть заменена на последовательность:
mov edx, id1/idconst1
sub eax, edx
Подобная оптимизация возможна и для операций сложения, умножения и деления.
3) Коммутативные операции сложения и умножения позволяют не менять порядок
операндов перед выполнением действия и потому при сложении следующую цепочку:
xchg eax, edx
add eax, edx
можно заменить на
add eax, edx .
4) Для операций сложения (add), вычитания (sub) и умножения (imul) разрешено
использовать в качестве второго операнда идентификатор или константу. Поэтому цепочку
mov edx, id1/iconst1
add еах, edx
можно заменить на
add еах, id1/iconst1 .
Приведем пример оптимизации кода, полученного в предыдущей задаче.
mov eax,C mov eax,C 1 mov eax,13 mov eax,13 mov eax,13
push eax push eax mov edx,A mov edx,A 4 add eax,A
mov eax,A 1 mov eax,13 xchg eax,edx 3 add eax,edx imul eax,D
push eax mov edx,A add eax,edx mov edx,D 4 mov edx,C
mov eax,13 xchg eax,edx mov edx,D imul eax,edx xchg eax,edx
pop edx add eax,edx imul eax,edx mov edx,C sub eax,edx
xchg eax,edx mov edx,D mov edx,C xchg eax,edx mov A, eax
add eax,edx imul eax,edx xchg eax,edx sub eax,edx
push eax 2 pop edx sub eax,edx mov A, eax
mov eax,D xchg eax,edx mov A, eax
pop edx sub eax,edx
xchg eax,edx mov A, eax
imul eax,edx
pop edx
xchg eax,edx
sub eax,edx
mov A, eax
Рис. 9. Результат оптимизации кода

4.3. Практические рекомендации по программированию


Некоторой сложностью в реализации метода является построение упорядоченного
дерева, соответствующего оператору присваивания. Для упрощения реализации возможно
использование линейного представления этого дерева в виде прямого порядка вершин или
левого скобочного представления. Построенное линейное представление дерева будет
являться входной информацией для требуемой программы. Таким образом, пример,
приведенный на рис. 3, может быть представлен как следующее левое скобочное
представление:
=(ABC,-(C,*(+(A,13),D))).
Данная запись легко может быть преобразована в бинарное дерево, по которому
генерируется код для целевой машины. Полученная кодовая последовательность должна
быть оптимизирована последовательным применением рассмотренных выше правил.
Простая грамматика арифметических выражений может быть представлена
следующими правилами.
E ::= id=T

14
T ::= T+F | T-F | F
F ::= F*I | F/I | I
I ::= id | const | (E)
Разбор в таком случае рекомендуется вести справа налево. Это связано с корректной
обработкой некоммутативных операций. При разборе справа налево выражения id1-id2-id3
будет сгенерировано дерево, описываемое как (id1-id2)-id3, тогда как при разборе слева
направо результат будет id1-(id2-id3), то есть неверным. Еще одним выходом может служить
преобразование грамматики от леворекурсивной к праворекурсивной.
E ::= id=T
T ::= FT’ | F
T’ ::= +F | -F|+FT|-FT
F ::= IF | I
F’ ::= *I | /I|*IF’ | /IF’ | I
I ::= id | const | (E)
Данные грамматики можно использовать и для непосредственной генерации кода без
промежуточного построения дерева. В этом случае каждому из операторов приписывается
последовательность кода, рассмотренная выше.

4.4. Генерация оптимального кода


Генерация оптимального кода возможна при анализе не отдельных вершин, а их триад,
то есть узла и его двух дочерних вершин. Генерация кода для унарных операторов при этом
не изменяется. Также неизменным остается код для операции присваивания.
Здесь будем считать, что id1/iconst1 – идентификатор или константа, записанная в левом
потомке текущей вершины, а id2/iconst2 – идентификатор или константа, записанная в
правом потомке.
1) Для любого бинарного оператора, имеющего в качестве обоих своих потомков
идентификатор или константу, генерируется следующий код:
mov eax, id1/iconst1
op еах, id2/iconst2 .
2) Для любого бинарного оператора, имеющего в качестве левого потомка поддерево с
бинарным оператором в корне и идентификатор или константу в качестве правого потомка,
генерируется следующий код:
C(l)
op еах, id2/iconst2 .
3) Для бинарного коммутативного оператора, имеющего в качестве правого потомка
поддерево с бинарным оператором в корне и идентификатор или константу в качестве левого
потомка, разрешается применить правило коммутативности. Это означает, что можно
принять левого потомка за правого и наоборот, сведя тем самым задачу к предыдущей.
Полученный код при этом будет иметь следующий вид:
C(r)
op еах, id1/iconst1 .
4) Для бинарного некоммутативного оператора, имеющего в качестве правого потомка
поддерево с бинарным оператором в корне и идентификатор или константу в качестве левого
потомка, генерируется следующий код:
C(r)
mov edx, id2/iconst2
xchg eax,edx
op eax,edx .
5) Для бинарного оператора, имеющего в качестве обоих потомков поддеревья с
бинарными операторами в корне, генерируется следующий код:
C(r)
push aex
C(l)
pop edx
15
op eax,edx .

Приведем пример генерации оптимального кода для рассмотренного дерева.


mov eax,13 A+13
add eax,A (A+13)*D
imul eax,D
mov edx,C C-(A+13)*D
xchg eax,edx
sub eax,edx
mov A, eax =
Рис. 10. Результат генерации оптимального кода

4.5. Генерация кода для логических выражений


Генерация кода производится и для логических выражений. Простая грамматика
логических выражений может быть представлена следующими правилами.
G ::= G or Q | Q
Q ::= Q and H | H
H ::= J | not J
J ::= T S T | T | (G)
S ::= < | > | >= | <= | == | <>
Здесь T – это правая часть арифметического выражения, описанная в разделе 4.4.
Логические операции or и and рекомендуется скомбинировать в двоичное дерево, а
разбор самого логического выражения вести слева направо. Это связано с тем, что
логические операции обладают следующим свойством.
1 or a = 1
0 and a = 0
То есть, в выражении or при встрече первого члена, равного 1, можно считать, что и все
остальное выражение равно 1 и не вести дальнейшие вычисления. В случае с логической
операцией and при первом встретившемся 0, значение всего выражения принимается равным
0 и дальнейшие вычисления не ведутся.
При генерации кода для арифметических выражений мы будем пользоваться тем
свойством, что операция cmp влияет на флажок Z. Однако так как принято обозначать ложь
нулем, а истину отличным от нуля значением, то в связи с такой неопределенностью проще
будет показывать, равен ли результат нулю. То есть после всех операций флажок Z будет
показывать результат, противоположный имеющемуся.
Сама генерация кода ведется по следующим шаблонам.
1) Для оператора or:
C(l)
jnz label1
C(r)
label1:

2) Для оператора and:


C(l)
jz label1
C(r)
label1:

3) Если операндами у операций or и and являются арифметические выражения (в том


числе единственный идентификатор или константа), то генерируется следующий код:
C(ar)
test ax,0

16
Здесь C(ar) – это код, сгенерированный для арифметического выражения.

4) Для оператора сравнения в общем случае шаблон выглядит следующим образом:


C(r)
push ax
C(l)
pop dx
cmp ax,dx
setxx ax
test ax,1

Данный шаблон оптимизируется как и арифметическое выражение. То есть, например,


при наличии двух непосредственных операндов шаблон не требует обращения к стеку и
будет выглядеть следующим образом:
mov ax,id1
mov dx,id2
cmp ax,dx
setxx ax
test ax,1

setxx здесь указывает на вид сравнения:


setne при операции ==;
sete при операции <>;
setg при операции <=;
setge при операции <;
setl при операции >=;
setle при операции >.

5) Для получения корректного результата в конце логического выражения необходимо


добавить следующий код:
setz ax
cmp ax,0

Вторым вариантом является учет инвертированности результата при его анализе.

Рис. 11. Дерево синтаксического разбора для логического выражения


A or (C<10 and D>=15) or B

17
Рассмотрим пример генерации кода для выражения A or (C<10 and D>=15) or B.

mov ax, A A
test ax,0
jnz label1
mov ax, C C>10
cmp ax,10
setge ax
test ax,1
jz label2 C>10 and D>=15 (C>10 and D>=15)
or B
mov ax, D D>=15 A or ((C>10 and D>=15)
cmp ax,15 or B)
setl ax
test ax,1
label2:
jnz label3
mov ax, B B
test ax,0
label3:
label1:
setz ax Хвостовой
cmp ax,0 код

Рис. 12. Результат генерации кода для выражения A or (C>10 and D>=15) or B

В дальнейшем сгенерированный код может быть оптимизирован следующим образом.


1) Фрагмент кода
jnz/jz labelN

labelN:
jz/jnz labelM

следует заменить на следующий:
jnz/jz labelN

jz/jnz labelM
labelN:

так как известно, что условия противоречат друг другу и второй переход не будет
выполнен.

2) Фрагмент кода
jz/jnz labelN

labelN:
jz/jnz labelM

следует заменить на следующий:
jnz/jz labelM

18
jz/jnz labelM

так как известно, что условия совпадают и второй переход будет выполнен в любом
случае.
Следует заметить, что в обоих случаях между меткой и командой условного перехода
могут стоять другие метки.

4.6. Варианты индивидуальных заданий


Разработать алгоритм и программу синтаксически управляемой трансляции простых
операторов присваивания, содержащих как целые, так и вещественные переменные. В состав
выражения могут входить операции сложения, вычитания, умножения и унарный минус.
Варианты.
1. Генерация кода с последующей его оптимизацией на языке ассемблера.
2. Генерация оптимального кода.
3. Генерация кода для арифметических выражений (арифметические выражения не
могут входить в состав логического).

Тестовые примеры.
1. A=-B+(C-D)*2+(E+100)*3
2. А1=D1*С1+(С2+02)*5-7
3. X=Y*Z*(B-C)*2+7
4. Y=(F1+F22)*10+7*(F13-F333)
5. А100=5*(А+D+C)*10-D
6. TABLE=(A+B)*R-F*(S-Y-Z)
7. Т11=(-A)*B+C*D-E10*E11
8. Z100=Z1*(Z2+Z3)-Z4*(Z5-Z6)
9. RES=(C10-C20)*10+5*X*(Y-100)
10. A and (B or (C<=10) or (D>=5))
11. ((A<5) and (A>-5)) or (A<>0)

19
5. НЕДЕТЕРМИНИРОВАННЫЕ КОНЕЧНЫЕ АВТОМАТЫ (НКА)

5.1. Определение
Недетерминированным конечным автоматом называется пятерка (K,VT, М, S, Z), где
1) К – алфавит элементов, называемых состояниями;
2) VT – алфавит, называемый входным алфавитом (литеры, которые могут встретиться в
цепочке или предложении);
3) М – отображение (или функция) множества K×VT в подмножество множества К;
4) S – множество начальных состояний S  К;
5) Z – непустое множество заключительных (допускающих) состояний, каждое из
которых принадлежит К.
Входная цепочка длины n допускается недетерминированным конечным автоматом
тогда и только тогда, когда найдется состояние Р, которое принадлежит одновременно M(S, n)
и множеству заключительных состояний Z.
Для представления такого автомата также используется матрица переходов, в ячейках
которой может быть указано множество переходов. Начальные состояния помечаются
каким-либо символом слева, например, стрелкой. В заданном автомате состояния А и В
являются начальными, В и С – заключительными.

0 1
A A,B C 0
B C 1
C A,C 1
Рис. 12. Недетерминированный КА

5.2. Методы построения КА по НКА


Для каждого недетерминированного конечного автомата существует
детерминированный конечный автомат, который допускает в точности те же входные
цепочки, что и недетерминированный.
Доказательство этого факта будет рассмотрено на примере алгоритма,
осуществляющего такое преобразование. Алгоритм определяется следующими пятью
шагами. Пусть Мн недетерминированный автомат, а Мд - эквивалентный ему
детерминированный автомат, который нужно построить.
1. Пометить первую строку таблицы переходов для Мд множеством начальных
состояний автомата Мд. Применить к этому множеству шаг 2.
2. По данному множеству состояний S, помечающему строку таблицы переходов
автомата Мд, для которой переходы еще не вычислены, вычислить те состояния Мн, которые
могут быть достигнуты из S с помощью каждого входного символа х, и поместить множества
последующих состояний в соответствующие ячейки таблицы для Мд. Символически это
выражается так: если  - функция, недетерминированных переходов, то функция
детерминированных переходов  задается формулой
`(S, x){s | s принадлежит (t, x) для некоторого t из S}
Таким образом, при объединении состояний мы объединяем и их переходы по
соответствующим терминалам.
3. Для каждого нового множества, порожденного переходами на шаге 2, посмотреть,
имеется ли уже в Мд строка, помеченная этим множеством. Если нет, то создать новую
строку и пометить ее этим множеством. Если множество уже использовалось как метка,
никаких действий не требуется.
4. Если в таблице автомата Мд есть строка, для которой еще не вычислены переходы, то
вернуться к шагу 2. Если все переходы вычислены, перейти к шагу 5.
5. Пометить строку как допускающее состояние автомата Мд тогда и только тогда, когда
она содержит допускающее состояние недетерминированного автомата. В противном случае

20
пометить её как отвергающее состояние.
В результате работы алгоритма число состояний полученного конечного распознавателя
может увеличиться до 2n состояний – по числу подмножеств исходного множества состояний.
Проиллюстрируем применение алгоритма следующим примером для автомата,
представленного на рисунке 10. Результат применения шага 1 изображен на рисунке 11a.
Применяя шаг 2 к {A, В}, обнаруживаем, что `({A, В}, 0) ={A, В} и '({A, В}, 1) - {С} (см.
рис. 11б).
Применяя шаг 3, мы видим, что уже имеется строка для {A, В}, но не для {С}. Поэтому
создаём новую строку для {С}, получая тем самым конфигурацию на рисунке 11в.
Переходя к шагу 4, обнаруживаем, что надо применить шаг 2 к {С}. После того, как это
сделано, на шаге 3 выясняется, что нужны ещё две строки (рис. 11г). Применение шага 2 к
{A, С} и к пустому множеству {} дает нам переходы во множества, которые уже являются
именами состояний. Этот результат изображен на рисунке 11д.
Теперь шаг 4 предписывает нам перейти к шагу 5. Состояние {A, В} отмечается как
допускающее, поскольку оно содержит допускающее состояние В; состояния {С} и {A, С}
отмечаются как допускающие, так как содержат допускающее состояние С. Пустое
множество, разумеется, не содержит допускающего состояния и поэтому помечается как
отвергающее.
Результат приведен на рисунке 11е, где изображен окончательный вариант
детерминированного автомата, эквивалентного исходному недетерминированному.
Вспоминая, что используемые множества представляют собой имена состояний, сделаем
замену и получим более простой вид автомата рис. 11ж.
0 1 0 1
{A,B} {A,B} {A,B} {C}
a) {C} {} {A,C}
{} {} {}
0 1 {A,C} {A,B} {A,C}
{A,B} {A,B} {C} д)
б)
0 1
{A,B} {A,B} {C} 1
0 1 {C} {} {A,C} 1
{A,B} {A,B} {C} {} {} {} 0
{C} {A,C} {A,B} {A,C} 1
в) е)

0 1 0 1
{A,B} {A,B} {C} 1 1 2 1
{C} {} {A,C} 2 3 3 1
{} 3 3 3 0
{A,C} 4 1 4 1
г) ж)

Рис. 13. Построение детерминированного КА из НКА

5.3. Построение детерминированного КА по регулярному выражению


Для построения детерминированного КА по заданному регулярному выражению
необходимо выполнить следующие шаги:
1) построить систему переходов;
2) построить диаграмму состояний по системе переходов;
3) построить НКА по диаграмме состояний;
4} построить КА по НКА.
Построение системы переходов
Пусть задано регулярное выражение r. Система переходов – это ориентированный граф
с одним начальным состоянием S и одним заключительным состоянием Z. Вершинами графа
21
являются состояния. На рис. 12 представлены системы переходов, соответствующие про-
стейшим регулярным выражениям.
Построение диаграммы состояний по системе переходов
Построение сводится к преобразованию системы переходов с целью устранения из нее
е-дуг (дуг, помеченных символом пустой цепочки ). Покажем алгоритм преобразования
системы переходов, который устраняет из нее по крайней мере одну дугу с пометкой .
1. Найти состояние, из которого выходит дуга с пометкой . Идти по этой дуге в
соответствующее состояние и далее по дугам с пометкой  до тех пор, пока дальнейший
переход по этому правилу не окажется невозможным, либо пока не будет возврата в
состояние, с которого начали.
2. Если дальнейший проход невозможен (т.е. мы оказались в состоянии В, и из которого
не выходит дуга с пометкой ), то выполняются следующие правила:
a) если состояние, из которого начался этот процесс, было начальным, то сделать В на-
чальным состоянием;
b) если В - заключительное состояние, то сделать предыдущее состояние А также
заключительным;
c) исключить дугу с-пометкой , ведущую в В из предыдущего состояния А;
d) в дополнение к каждой дуге, ведущей из В в некоторое состояние С, вывести дугу с
такой же пометкой, ведущую из А в С.
3. Если в результате выполнения п. 1 мы вернулись в исходное состояние, то
отождествить все состояния полученного цикла, исключив соединяющие их дуги с пометкой
. Если какое-либо из состояний этого цикла было начальным (заключительным), то
включить новое состояние в множество начальных (заключительных).

Рис. 14. Система переходов для регулярных выражений


Проиллюстрируем применение алгоритма следующим примером. Построить конечный
автомат по заданному регулярному выражению a+b+.
1) Построим систему переходов

2) Устраним  - дуги для получения диаграммы состояний автомата

3) В результате устранения недостижимых состояний получим диаграмму состояний

22
где А - начальное состояние, С - заключительное состояние.

5.4 Варианты заданий

Необходимо написать программу, реализующую построение ДКА по цепочкам вида


Z=1++1*01(11+01)+. Программа должна строить НКА по введенной строке и преобразовывать
его в ДКА.
Программа должна иметь возможность работать и с другими цепочками. Например:
1) Z=1++1*00(00+ll)* ;
2) Z=(0+1)*(1+00)(0+1)* ;
3) Z=(ll+01)*(1*+l*01) ;
4) Z=(0+l)*+00+(01+10)* ;
5) Z=ll+(0+10)(10)* .

23
6. АВТОМАТЫ С МАГАЗИННОЙ ПАМЯТЬЮ (МП - АВТОМАТЫ)
Конечные автоматы могут решать только такие вычислительные задачи, которые
требуют фиксированного и конечного объема памяти. В компиляторах возникает много задач,
для которых такие ограничения не выполняются. Память КА расширяется за счет
дополнительного механизма хранения информации - магазина или стека. Такие МП-автоматы
могут с успехом применяться для разбора контекстно-свободных грамматик. Правила КС-
грамматик имеют вид:
U::= u, где UVN, u(VNVT).

6.1. Определение
Автомат с магазинной памятью определяется следующими пятью объектами:
1) конечным множеством входных символов, в которое входит концевой маркер;
2) конечным множеством магазинных символов, включающим маркер дна;
3) конечным множеством состояний, включающим начальное состояние и множество
заключительных состояний;
4) начальным содержимым магазина, которое представляет собой маркер дна, за
которым следует (возможно пустая) цепочка других магазинных символов;
5) управляющим устройством, которое каждой комбинации входного символа, магазин-
ного символа и состояния ставит в соответствие выход и переход. Переход в отличие от
выхода заключается в выполнении операций над магазином, состоянием и входом. Операции,
которые запрашивали бы входной символ после концевого маркера или выталкивали из
магазина, а также вталкивали в него маркер дна, исключаются.
МП-автомат называется распознавателем, если имеет два выхода: допустить и
отвергнуть.

6.2. Построение примитивного МП - автомата


Для построения МП-автомата формализуем операции, которые может выполнять управ-
ляющее устройство автомата. Примитивный автомат может выполнять следующие опера-
ции:
над стеком:
• вытолкнуть символ;
• втолкнуть символ(ы);
• оставить магазин без изменений;
над входной цепочкой:
• сдвиг;
• держать;
над состоянием:
• перейти в заданное состояние.
МП-автомат удобно представлять совокупностью таблиц, описывающих управляющее
устройство автомата. Число таких таблиц соответствует числу состояний автомата. Число
столбцов таблиц определяется числом символов входного алфавита плюс концевой маркер.
Число строк соответствует числу магазинных символов плюс маркер дна. Каждый элемент
таблицы содержит набор действий, выполняемых автоматом в данном состоянии при
соответствующем входном символе и символе на вершине магазина. Строят автомат путем
формирования таблиц управляющего устройства.
Приведем пример МП-автомата, распознающего цепочки вида {0n1n | n > 0}.
1. Множество входных символов: (0,1, }.
2. Множество магазинных символов: {, Z};
 – маркер дна; bottom marker
Z – представляет входной символ "0".
3. Множество состояний {S1, S2} где:
S1 – соответствует фазе вталкивания Z в магазин для символа "0";
24
S2 – соответствует фазе выталкивания Z при появлении "1" во входной цепочке.
4. Начальное содержимое магазина: .
5. Управляющее устройство, представленное на рис. 13.
S1
0 1 
Z Состояние S1, Втолк. (Z) Состояние S2, Вытолк., Отвергнуть
Сдвиг Сдвиг
 Состояние S1, Втолк. (Z) Отвергнуть Отвергнуть
Сдвиг
S2
0 1 
Z Отвергнуть Состояние S2, Вытолк., Отвергнуть
Сдвиг
 Отвергнуть Отвергнуть Допустить

Рис. 15. Управляющее устройство примитивного МП-автомата

6.3. Построение непримитивного МП-автомата, осуществляющего


заданный перевод
Набор операций над магазином у непримитивного МП - автомата расширен введением
операции заменить. Операция ЗАМЕНИТЬ(АВС) эквивалентна четырем следующим
операциям над магазином: ВЫТОЛКНУТЬ, ВТОЛКНУТЬ(А), ВТОЛКНУТЬ(В),
ВТОЛКНУТЬ(С), "С" будет верхним символом магазина. Управляющее устройство
непримитивного МП-автомата реализуется одним состоянием.
Вернемся к задаче распознавания цепочек вида {0 n1 n | n > 0} и построим другой МП -
автомат. В предыдущем примере соответствующая фаза автомата фиксировалась
управляющим состоянием S1 и S2. Теперь для того чтобы различать фазы, введем новый
магазинный символ X, который будет храниться в верхней ячейке магазина на фазе
вталкивания. Когда впервые во входной цепочке появляется "1", X выталкивается из магазина
и автомат сопоставляет символы Z и "1". Наличие расширенной операции ЗАМЕНИТЬ
позволяет реализовать этот алгоритм с помощью одного состояния.
0 1 
Х Заменить(ZХ) Сдвиг Вытолк. Держать Отвергнуть

Z Отвергнуть Вытолк. Сдвиг Отвергнуть

 Отвергнуть Отвергнуть Допустить

Начальное содержимое магазина: X


Рис. 16. Управляющее устройство МП-автомата с операцией ЗАМЕНИТЬ

Помимо функции распознавания МП-автомат может выполнять и операцию перевода


или только перевода. Приведем пример МП автомата, выполняющего перевод произвольной
цепочки из "0" и "1" (0+1)* в цепочку вида 0n1m.
Управляющее устройство может производить наряду с обычными операциями над
состоянием, входом и магазином операцию на выходе, т. е. МП - автомат способен порождать
цепочки. Для этого используется операция ВЫДАТЬ.

25
0 1 J
А Втолкнуть (А), Сдвиг Выдать (1), Сдвиг Вытолк., Выдать (0),
Держать

 Втолкнуть (А), Сдвиг Выдать (1), Сдвиг Допустить

Начальное содержимое магазина: 


Рис. 17. Управляющее устройство МП-автомата, выполняющего перевод

Анализ работы управляющего устройства показывает, что "1" во входной цепочке


выдается сразу, а "0" помещается в магазин. Когда встречается маркер конца цепочки,
автомат выталкивает "0" из магазина и выдает их.

6.4. Варианты индивидуальных заданий


I. Построить примитивный МП - автомат. Показать последовательность его
конфигураций для распознавания.
1. Множества цепочек из нулей и единиц, где число единиц равно числу нулей;
2. {wwr | w={{a.b}+}, здесь r – реверсия цепочки;
3. (1 n 0m | n>m≥0);
4. {1 n 0m1m0 n | n,m≥l};
5. {1 n 0m | n>m≥0};
6. {1 n 0 n 1m0m | n,m>0};
7. {1 n 0m | m>n≥0}.
II. Построить непримитивный МП-автомат (постараться найти автомат с одним
состоянием), который будет выполнять следующие переводы:
1. 1 n 0m в 1 n 22m, n>0 ,m>0;
2. 1 n 0m1 n 0m в 1m0m+n, n>0, m>0 (разрешается использование нескольких стеков);
3. bi в (bi+1)r, где bi – цепочка из нулей и единиц, являющаяся бинарным пред-
ставлением числа i, здесь r – операция побитовой инверсии;
4. 1m-n , если m>n
1m0n в 0n-m, если n>m
1, если m=n
n m
5. 0 1 в 012n02m0, n>0, m>0.

Выбор варианта
Первая группа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1
Вторая группа.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4
2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2

26
7. КОНТРОЛЬНЫЕ ВОПРОСЫ ПО КУРСУ
1. Какой граф называется деревом?
2. Какой порядок вершин является достаточным для представления дерева: прямой или
обратный?
3. Разработайте алгоритм построения остова связанного неориентированного графа.
Остовом связанного неориентированного графа G называется дерево с ребрами из графа G,
содержащее все его вершины.
4. Для чего служит синтаксически управляемая трансляция?
5. В чем сущность оптимизации кода синтаксически управляемой трансляции?
6. Постройте схему синтаксически управляемой трансляции арифметических
выражений, содержащих как целые, так и вещественные переменные. Тип каждого
идентификатора известен.
7. Идентификатор в некотором языке состоит из последовательности, включающей до
шести букв и цифр, первая литера из которых должна быть буквой. Постройте:
a) регулярное выражение для идентификатора;
b) КС-грамматику, генерирующую все без исключения идентификаторы языка.
8. Что называется конечным автоматом?
9. Существует ли связь между конечным автоматом и регулярным выражением?
10. Для какого недетерминированного автомата можно построить соответствующий
детерминированный? Что можно сказать о максимальном числе состояний у полученного де-
терминированного автомата?
11. Покажите, какие из следующих множеств регулярны, и напишите для них
регулярные выражения:
a) множество цепочек с равным числом нулей и единиц;
b) множество цепочек из {0,1)* с четным числом нулей и нечетным числом единиц;
c) множество цепочек из {0,1}*, длина которых делится на 3.
12. Опишите алгоритм, который по данной регулярной грамматике G и цепочке w
определяет, принадлежит ли w языку L(G).
13. Докажите, что каждое регулярное множество порождается регулярной грамматикой.
14. Напишите программу, которая воспринимает в качестве входа конечный автомат и
выдает на выходе эквивалентное регулярное выражение.
15. Что такое стек? Какие существуют операции со стеком?
16. Каковы преимущества непримитивного МП - автомата?
17. Покажите, что следующие языки не являются контекстно-свободными:
a) {anbncn| n≥0};
b) (ai | i- простое число).
18. Покажите, что каждый КС-язык допускается МП-автоматом, который за один такт
увеличивает длину магазина не более чем на единицу.
19. Постройте МП-автоматы, допускающие следующие языки:
a) {0i1j | i ≥ j};
b) {w | w состоит из равного числа символов а и b).
20. Приведите иерархию КС-грамматик.
21. Сравните нисходящий разбор с восходящим.

27
8. ПРАВИЛА ВЫБОРА ВАРИАНТА ЗАДАНИЯ
Задания выполняются индивидуально. В качестве номера варианта студент берет
остаток от деления своего номера по списку на количество вариантов. Столбцы таблицы
выбора вариантов соответствуют номерам бригад, а количество строк соответствует числу
заданий. Пересечение соответствующего столбца со строкой содержит номер пункта задания.

9. БИБЛИОГРАФИЧЕСКИЙ СПИСОК
1. S. Muchnik “Advanced Сompiler Design & Implementation” 1999.
2. A. Axo, Р. Сети, Дж. Ульман. Компиляторы: принципы, технологии, инструменты М.:
Вильямс, 2001.
3. Д. Грис. Конструирование компиляторов для цифровых вычислительных машин. М.:
Мир, 1975.
4. Дж. Донован. Системное программирование. М. Мир, 1975.
5. Ф. Льюис, Д. Розенкранц, Р. Стирнз. Теоретические основы проектирования
компиляторов. М.: Мир, 1979.
6. Дж. Фостер. Автоматический синтаксический анализ. /Пер. с англ. В.В. Мартынюка.
М.: Мир, 1975.
7. Р. Хантер. Основные концепции компиляторов. М: Вильямс, 2002.

28
Учебное издание

Лингвистическое обеспечение САПР

Составители:
ЗАЙЦЕВА Лариса Викторовна
КЛЫШИНСКИЙ Эдуард Станиславович
ЁЛКИН Сергей Владимирович

Редактор С.П. Клышинская


Технический редактор О.Г. Завьялова

http://www.miem.edu.ru/rio/
rio@miem.edu.ru

Подписано в печать . .07. Формат 60х84/16.


Бумага типографская № 2. Печать - ризография.
Усл.печ. л. 1,81 Уч.-изд. л. 1,63 Тираж 50 экз.
Заказ . Бесплатно Изд № .
Московский государственный институт электроники и математики
109028 Москва, Б. Трехсвятительский пер., 3/12.
Отдел оперативной полиграфии Московского государственного института
электроники и математики.
113054 Москва, ул. М. Пионерская, 12.

29