
- •Содержание
- •1 Формальные языки и грамматики
- •1.1 Основные понятия теории формальных языков
- •Определение Цепочка, которая не содержит ни одного символа, называется пустой цепочкой и обозначается .
- •1.2 Способы задания языков
- •1.2.1 Формальные грамматики
- •1.2.1.1 Определение формальной грамматики
- •Определение Цепочка (vtvn)* выводима из цепочки в грамматике(обозначается*), если существует последовательность цепочек (n0) такая, что .
- •1.2.1.3 Эквивалентность грамматик
- •1.2.2 Формы Бэкуса - Наура
- •1.2.3 Диаграммы Вирта
- •1.2.5 Механизмы распознавания языков
- •1.2.5.1 Определение распознавателя
- •1.2.5.2 Схема работы распознавателя
- •1.2.5.3 Классификация распознавателей
- •2 Регулярные грамматики и языки
- •2.1 Регулярные выражения
- •2.2 Лемма о разрастании языка
- •2.3 Конечные автоматы
- •2.3.1 Определение конечного автомата
- •2.3.2 Распознавание строк конечным автоматом
- •Существуют следующие способы представления функции переходов: - командный способ.Каждую команду ка записывают в форме , где.
- •2.3.3 Преобразование конечных автоматов
- •2.3.3.1 Преобразование конечного автомата к детерминированному виду
- •Алгоритм Преобразование нка в дка
- •2.3.3.2 Минимизация конечного автомата
- •2.3.3.2.1 Устранение недостижимых состояний ка
- •2.3.3.2.2 Объединение эквивалентных состояний ка Алгоритм Объединение эквивалентных состояний ка
- •2.4 Взаимосвязь способов определения грамматик
- •2.4.1 Построение ка по регулярной грамматике
- •Выход:ка.
- •3 Контекстно-свободные языки и грамматики
- •3.1 Задача разбора
- •3.1.1 Вывод цепочек
- •Определение Цепочка (vtvn)* выводима из цепочки в грамматике(обозначается*), если существует последовательность цепочек (n0) такая, что .
- •3.1.2 Дерево разбора
- •3.1.2.1 Нисходящее дерево разбора
- •3.1.2.2 Восходящее дерево разбора
- •3.1.3 Однозначность грамматик
- •3.2 Преобразование кс-грамматик
- •3.2.1 Проверка существования языка грамматики
- •3.2.2 Устранение недостижимых символов
- •Алгоритм Устранение нетерминалов, не порождающих терминальных строк Вход: кс-грамматика.
- •Алгоритм Устранение недостижимых символов Вход: кс-грамматика.
- •Определим множество достижимых символов z грамматики g, т.Е. Множество
- •3.2.3 Устранение -правил Алгоритм Устранение -правил Вход: кс-грамматика.
- •3.2.4 Устранение цепных правил Алгоритм Устранение цепных правил Вход: кс-грамматика.
- •3.2.5 Левая факторизация правил Алгоритм Устранение левой факторизации правил Вход: кс-грамматика.
- •3.2.6 Устранение прямой левой рекурсии Алгоритм Устранение прямой левой рекурсии Вход: кс-грамматика.
- •3.3 Автомат с магазинной памятью
- •3.3.1 Определение мп-автомата
- •3.3.2 Разновидности мп-автоматов
- •3.3.3 Взаимосвязь мп-автоматов и кс-грамматик
- •3.3.3.1 Построение мп-автомата по кс-грамматике
- •3.3.3.2 Построение расширенного мп-автомата по кс-грамматике
- •3.4 Нисходящие распознаватели языков
- •3.4.1 Рекурсивный спуск
- •3.4.1.1 Сущность метода
- •3.4.1.2 Достаточные условия применимости метода рекурсивного спуска
- •3.4.2 Распознаватели ll(k)-грамматик
- •3.4.2.1 Определение ll(k)-грамматики
- •3.4.2.2 Необходимое и достаточное условие ll(1)-грамматики
- •3.4.2.3 Построение множества first(1, a)
- •3.4.2.4 Построение множества follow(1, a)
- •3.4.2.5 Алгоритм «сдвиг-свертка» для ll(1)-грамматик
- •Шаг 6. Получили следующую цепочку вывода:
- •3.5.1.1.2 Поиск основы сентенции грамматики
- •3.5.1.1.3 Построение множеств l(a) и r(a)
- •3.5.1.1.5 Алгоритм «сдвиг - свертка» для грамматик простого предшествования
- •Шаг 3. Функционирование распознавателя для цепочки (((aa)a)a) показано в таблице 3.9.
- •3.5.1.2 Грамматика операторного предшествования
- •3.5.1.2.1 Определение грамматики операторного предшествования
- •3.5.1.2.2 Построение множеств Lt(a) и Rt(a)
- •3.5.1.2.4 Алгоритм «сдвиг-свертка» для грамматики операторного предшествования
- •3.5.2 Распознаватели lr(k)-грамматик
- •3.6 Соотношение классов кс-грамматик и кс-языков
- •3.6.1 Соотношение классов кс-грамматик
- •3.6.2 Соотношение классов кс-языков
- •4 Принципы построения языка
- •4.1 Лексика, синтаксис и семантика языка
- •4.2 Определение транслятора, компилятора, интерпретатора и ассемблера.
- •4.3 Общая схема работы компилятора
- •4.4 Лексический анализ
- •4.4.1 Задачи лексического анализа
- •4.4.2 Диаграмма состояний с действиями
- •4.4.3 Функция scanner
- •4.5 Синтаксический анализатор программы
- •4.5.1 Задача синтаксического анализатора
- •4.5.2 Нисходящий синтаксический анализ
- •Теорема Достаточные условия применимости метода рекурсивного спуска
- •4.6 Семантический анализ программы
- •4.6.1 Обработка описаний
- •4.6.2 Анализ выражений
- •4.6.3 Проверка правильности операторов
- •4.7 Генерация кода
- •4.7.1 Формы внутреннего представления программы
- •4.7.1.1 Тетрады
- •4.7.1.2 Триады
- •4.7.1.3 Синтаксические деревья
- •4.7.1.4 Польская инверсная запись
- •Составной оператор begin s1; s2;...; Sn end в полиЗе записывается как s1 s2... Sn.
- •4.7.1.5 Ассемблерный код и машинные команды
- •4.7.2 Преобразование дерева операций в код на языке ассемблера
- •4.8 Оптимизация кода
- •4.8.1 Сущность оптимизации кода
- •4.8.2 Критерии эффективности результирующей программы
- •4.8.3 Методы оптимизации кода
- •4.8.4 Оптимизация линейных участков программ
- •4.8.4.1 Свертка объектного кода
- •4.8.4.2 Исключение лишних операций
- •4.8.5 Оптимизация логических выражений
- •4.8.6 Оптимизация циклов
- •4.8.7 Оптимизация вызовов процедур и функций
- •4.8.9 Машинно-зависимые методы оптимизации
- •4.8.9.1 Распределение регистров процессора
- •4.8.9.2 Оптимизация кода для процессоров, допускающих распараллеливание вычислений
- •5 Формальные методы описания перевода
- •5.1 Синтаксически управляемый перевод
- •5.1.1 Схемы компиляции
- •5.1.4 Практическое применение су-схем
- •5.2 Транслирующие грамматики
- •5.2.1 Понятие т-грамматики
- •5.3 Атрибутные транслирующие грамматики
- •5.3.1 Синтезируемые и наследуемые атрибуты
- •5.3.2 Определение и свойства ат-грамматики
- •5.3.3 Формирование ат-грамматики
- •Решение
4.8.4.1 Свертка объектного кода
Свертка объектного кода — это выполнение во время компиляции тех операцийисходной программы, для которых значения операндов уже известны. Нет необходимости многократно выполнять эти операции в результирующей программе — вполне достаточно один раз выполнить их при компиляции программы.
Алгоритм свертки для линейного участка программы работает со специальной таблицей Т, которая содержит пары (<переменная>,<константа>) для всех переменных, значения которых уже известны.
Рассмотрим выполнение алгоритма свертки объектного кода для триад. Для пометки операций, не требующих порождения объектного кода, будем использовать триады специального вида С (k, 0).
Алгоритм свертки триад последовательно просматривает триады линейного участка и для каждой триады делает следующее:
1 Если операнд есть переменная, которая содержится в таблице Т, то операнд заменяется на соответствующее значение константы.
2 Если операнд есть ссылка на особую триаду типа С(k, 0), то операнд заменяется на значение константы k.
3 Если все операнды триады являются константами, то триада может быть свернута. Тогда данная триада выполняется и вместо нее помещается особая триада вида С(k,0), где k — константа, являющаяся результатом выполнения свернутой триады. (При генерации кода для особой триады объектный код не порождается, а потому она в дальнейшем может быть просто исключена.)
Если триада является присваиванием типа А:=В, тогда:
- если В — константа, то А со значением константы заносится в таблицу Т (если там уже было старое значение для А, то это старое значение исключается);
- если В — не константа, то А вообще исключается из таблицы Т, если оно там есть.
Рассмотрим пример выполнения алгоритма.
Пусть фрагмент исходной программы (записанной на языке типа Pascal) имеет вид:
I:=1+1;
I:=3;
J:=6*I+I
Ее внутреннее представление в форме триад будет иметь вид:
1 +(1,1);
2 :=(I,^1);
3 := (I,3);
4 *(6,I);
5 +(^4, I);
6 :=(J,^5).
Процесс выполнения алгоритма свертки показан в табл. 4.7.
Таблица 4.7 Пример работы алгоритма свертки
Триада |
Шаг 1 |
Шаг 2 |
ШагЗ |
Шаг 4 |
Шаг 5 |
Шаг 6 |
1 |
С (2, 0) |
С (2, 0) |
С (2, 0) |
С (2, 0) |
С (2, 0) |
С (2, 0) |
2 |
:= (I, ^1) |
:=(I,2) |
:=(I,2) |
:=(I,2) |
:=(I,2) |
:=(I,2) |
3 |
:=(I,3) |
:=(I,3) |
:=(I,3) |
:=(I,3) |
:=(I,3) |
:=(I,3) |
4 |
*(6,I) |
* (6,I) |
*(6,I) |
С (18, 0) |
С (18, 0) |
С (18, 0) |
5 |
+ (^4, I) |
+ (^4, I)
|
+ (^4, I)
|
+ (^4, I) |
С (21,0) |
С (21, 0) |
6 |
:=(J,^5) |
:=(J,^5) |
:=(J,^5) |
:=(J,^5) |
:=(J,^5) |
:=(J,21) |
Т |
(,) |
(I, 2) |
(I,3) |
(I, 3) |
(I, 3) |
(I, 3) (J,21) |
Если исключить особые триады типа С(k,0) (которые не порождают объектногокода), то в результате выполнения свертки получим следующую последовательность триад:
1 := (I, 2)
2 := (I, 3)
3 := (J, 21)
4.8.4.2 Исключение лишних операций
Алгоритм исключения лишних операций просматривает операции в порядке их следования. Так же как и алгоритму свертки, алгоритму исключения лишних операций проще всего работать с триадами, потому что они полностью отражают взаимосвязь операций.
Рассмотрим алгоритм исключения лишних операций для триад.
Чтобы следить за внутренней зависимостью переменных и триад, алгоритм присваивает им некоторые значения, называемые числами зависимости, по следующим правилам:
1) изначально для каждой переменной ее число зависимости равно 0, так как в на чале работы программы значение переменной не зависит ни от какой триады;
2) после обработки i-й триады, в которой переменной А присваивается некоторое значение, число зависимостиA(dep(A)) получает значениеi, так как значение А теперь зависит от данной i-й триады;
3) при обработке 1-й триады ее число зависимости (depd)) принимается равнымзначению 1+(максимальное из чисел зависимости операндов).
Таким образом, при использовании чисел зависимости триад и переменных можно утверждать, что если i-я триада идентична j-й триаде (j<i), то i-я триада считается лишней в том и только в том случае, когда dep(i)=dep(j).
Алгоритм исключения лишних операций использует в своей работе триады особого вида SAME(j, 0). Если такая триада встречается в позиции с номером i, то это означает, что в исходной последовательности триад некоторая триада i идентична триаде j.
Алгоритм исключения лишних операций последовательно просматривает триады линейного участка. Он состоит из следующих шагов, выполняемых для каждой триады:
1 Если какой-то операнд триады ссылается на особую триаду вида SAME(j,0), то он заменяется на ссылку на триаду с номеромj(^j).
2 Вычисляется число зависимости текущей триады с номером i, исходя из чисел зависимости ее операндов.
3 Если в просмотренной части списка триад существует идентичная j-я триада, причемj<iиdep(i)=dep(j), то текущая триадаiзаменяется на триаду особого видаSAME(j,0).
4 Если текущая триада есть присвоение, то вычисляется число зависимости соответствующей переменной.
Рассмотрим работу алгоритма на примере:
D:=D+C*B;
A:=D+C*B;
C:=D+C*B;
Этому фрагменту программы будет соответствовать следующая последовательность триад:
1) * (С, В)
2) + (D, ^1)
3) :=(D, ^2)
4)* (С, В)
5)+ (D, ^4)
6) :=(А, ^5)
7)* (С, В)
8)+ (D, ^7)
9):= (С, ^8)
Видно, что в данном примере некоторые операции вычисляются дважды над одними и теми же операндами, а значит, они являются лишними и могут быть исключены. Работа алгоритма исключения лишних операций отражена в табл. 4.8.
Таблица 4.8 Пример работы алгоритма исключения лишних операций
Обрабатываемая триада i |
Числа зависимости переменных |
Числа зависимости триад dep(i) |
Триады, полученные после выполнения алгоритма | |||
А |
В |
С |
D | |||
1)*(С,В) |
0 |
0 |
0 |
0 |
1 |
1) * (С, В) |
2)+(D,^l) |
0 |
0 |
0 |
0 |
2 |
2) + (D, ^1) |
3) := (D, ^2) |
0 |
0 |
0 |
3 |
3 |
3):=(D, ^2) |
4) * (С, В) |
0 |
0 |
0 |
3 |
1 |
4) SAME (1,0) |
5) + (D, ^4) |
0 |
0 |
0 |
3 |
4 |
5) + (D, ^1) |
6):= (А, ^5) |
6 |
0 |
0 |
3 |
5 |
6):= (А, ^5) |
7) * (С, В) |
6 |
0 |
0 |
3 |
1 |
7) SAME (1, 0) |
8) + (D, ^7) |
6 |
0 |
0 |
3 |
4 |
8) SAME (5, 0) |
9):=(С,^8) |
6 |
0 |
9 |
3 |
5 |
9):= (С, ^5) |
Теперь, если исключить триады особого вида SAME( j, 0), то в результате выполнения алгоритма получим следующую последовательность триад:
1) * (С, В)
2) + (D, ^1)
3) := (D, ^2)
4) + (D, ^1)
5) := (А, ^4)
:= (С, ^4)