
- •Содержание
- •Введение
- •1.3. Множества цепочек
- •1.4. Языки
- •1.5. Алгоритмы
- •1.6. Некоторые понятия теории графов
- •Контрольные вопросы
- •2. Введение в компиляцию
- •2.1. Задание языков программирования
- •2.2. Синтаксис и семантика
- •2.3. Процесс компиляции
- •2.4. Лексический анализ
- •2.5. Работа с таблицами
- •Переменная с плавающей точкой
- •2.6. Синтаксический анализ
- •2.7. Генератор кода
- •2.8. Оптимизация кода
- •2.8. Оптимизация кода
- •2.9. Исправление ошибок
- •2.10. Резюме
- •Контрольные вопросы
- •3. Теория языков
- •3.1. Способы определения языков
- •3.2. Грамматики
- •3.4. Распознаватели
- •3.5. Регулярные множества, их распознавание и порождение
- •5.2. LR(1) - таблица разбора
- •5.3. Построение LR – таблицы разбора
- •5.4. Сравнение LL – и LR – методов разбора
- •Контрольные вопросы
- •6. Оптимизация кода
- •6.1. Оптимизация линейного участка
- •6.1.1. Модель линейного участка
- •6.1.2. Преобразование блока
- •6.1.3. Графическое представление блоков
- •6.1.4. Критерий эквивалентности блоков
- •6.1.5. Оптимизация блоков
- •6.1.6. Алгебраические преобразования
- •6.2. Арифметические выражения
- •6.2.1. Модель машины
- •6.2.2. Разметка дерева
- •6.2.3. Программы с командами STORE
- •6.2.4. Влияние некоторых алгебраических законов
- •6.3. Программы с циклами
- •6.3.1. Модель программы
- •6.3.2. Анализ потока управления
- •Алгоритм вычисления прямого доминирования
- •6.3.3. Примеры преобразования программ
- •Удаления бесполезных операторов
- •Замена сложных операций
- •6.3.4. Оптимизация циклов
- •Перемещение кода
- •Индуктивное перемещение
- •Замена сложных операций
- •6.4. Анализ потоков данных
- •6.4.1. Интервалы
- •6.4.2. Анализ потоков данных с помощью интервалов
- •6.4.3. Несводимые графы управления
- •7. Включение действий в синтаксис
- •7.1. Получение четверок
- •7.2. Работа с таблицей символов
- •Контрольные вопросы
- •8. Проектирование компиляторов
- •8.1. Число проходов
- •8.2. Таблицы символов
- •8.3. Таблица видов
- •Контрольные вопросы
- •9. Распределение памяти
- •9.1. Стек времени прогона
- •9.2. Методы вызова параметров
- •9.3. Обстановка выполнения процедур
- •9.4. «Куча»
- •9.5. Счетчик ссылок
- •9.6. Сборка мусора
- •Контрольные вопросы
- •10. Генерация кода
- •10.1. Генерация промежуточного кода.
- •10.2. Структура данных для генерации кода
- •10.3. Генерация кода для типичных конструкций
- •10.3.1. Присвоение
- •10.3.2. Условные зависимости
- •10.3.3. Описание идентификаторов
- •10.3.4. Циклы
- •10.3.5. Вход и выход из блока
- •10.3.6. Прикладные реализации
- •10.4. Проблемы, связанные с типами
- •10.5. Время компиляции и время прогона
- •Контрольные вопросы
- •11. Исправление и диагностика ошибок
- •11.1. Типы ошибок
- •11.2. Лексические ошибки
- •11.3. Ошибки в употреблении скобок
- •11.4. Синтаксические ошибки
- •11.5. Методы исправления синтаксических ошибок
- •11.6. Предупреждения
- •11.7. Сообщения о синтаксических ошибках
- •11.8. Контекстно-зависимые ошибки
- •11.9. Ошибки, связанные с употреблением типов
- •11.10. Ошибки, допускаемые во время прогона
- •Контрольные вопросы
- •Список литературы
93
1)сдвиг, во время которого считывается и помещается в стек символ. Это соответствует движению на один пункт вдоль какогонибудь правила грамматики;
2)приведение, во время которого множество элементов в верхней части стека замещаются каким-либо нетерминалом грамматики с помощью одного из порождающих правил этой грамматики.
5.2. LR(1) - таблица разбора
Выше мы рассмотрели технологию разбора«снизу вверх». Однако при этом не обсуждался вопрос, как решить, следует ли выполнять конкретное приведение, когда правая часть правила появляется в вершине стека. Механизмом, который регулирует вопрос принятия правильного решения, является таблица разбора.
Таблица представляет собой матрицу. Она состоит из столбцов для каждого терминала и нетерминала грамматики плюс знак окончания и строк, соответствующих каждому состоянию, в котором может находиться анализатор. Каждое состояние соответствует той позиции в порождающем правиле, которой достиг анализатор. Таблица разбора для грамматики
1)S ® real IDLIST
2)IDLIST ® IDLIST, ID
3)IDLIST ® ID
4)ID ® A | B | C |D
приведена в табл. 5.1. Драйвер анализатора использует еще и два стека
– стек символов и стек состояний. Таблица разбора включает элементы четырех типов.
1)Элементы сдвига. Эти элементы имеют видS7 и означают: поместить в стек символ, соответствующий столбцу; поместить в стек состояний 7 и перейти к состоянию 7; если входной символ – терминал, принять его.
2)Элемент приведения. Он имеет вид R4 и означает: выполнить приведение с помощью правила4), т.е., допустив, что n есть число символов в правой части правила4), удалить n элемен-
тов из стека символов и n элементов из стека состояний и перейти к состоянию, указанному в верхней части стека состояний. Нетерминал в левой части правила(4) нужно считать следующим входным символом.
3)Элемент ошибок. Эти элементы являются пробелами в таблице и соответствуют синтаксическим ошибкам.
4)Элемент остановки. Им завершается разбор.
94
|
|
|
|
|
|
|
Таблица 5.1. |
|
Состояние |
S |
IDLIST |
ID |
real |
«,» |
A |
|
^ |
|
|
|
|
|
|
B |
|
|
|
|
|
|
|
|
C |
|
|
|
|
|
|
|
|
D |
|
|
1 |
HALT |
S5 |
S4 |
S2 |
|
S3 |
|
|
2 |
|
|
R4 |
|
R4 |
|||
3 |
|
|
|
|
|
|
||
4 |
|
|
|
|
R3 |
|
|
R3 |
5 |
|
|
|
|
S6 |
S3 |
|
R1 |
6 |
|
|
|
|
R2 |
|
R2 |
|
7 |
|
|
|
|
|
|
Рассмотрим, как с помощью вышеописанной таблицы разбирается строка:
real A, B, C ^
|
Стек |
|
Стек |
|
символов |
|
состояний |
real A, B, C ^ |
|
|
1 |
входной символ real – из элемента таблицы (1, real), сдвиг в состояние
2;
real A, B, C ^ |
|
|
2 |
|
real |
|
1 |
|
|
входной символ А – сдвиг в состояние |
|
|
||
3; |
|
|
|
|
|
А |
|
3 |
|
real A, B, C ^ |
real |
|
2 |
|
|
|
|
1 |
|
входной символ – «,», приведение по правилу (4); |
|
2 |
|
|
real A, B, C ^ |
|
|
|
|
real |
|
1 |
|
|
|
|
|
||
входной символ – ID, сдвиг в состояние 4; |
|
4 |
|
|
|
ID |
|
|
|
real A, B, C ^ |
|
2 |
|
|
|
real |
|
1 |
|
входной символ – «,», приведение по правилу (3); |
|
2 |
|
|
real A, B, C ^ |
|
|
|
|
real |
|
1 |
|
|
входной символ – IDLIST, сдвиг в |
|
|
||
состояние 5; |
|
5 |
|
|
|
IDLIST |
|
|
|
real A, B, C ^ |
|
2 |
|
|
|
real |
|
1 |
|
входной символ – «,», сдвиг в состояние 6;
|
95 |
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
|
||
real A, B, C ^ |
|
, |
|
|
5 |
|
|
IDLIST |
|
|
2 |
|
|
|
|
|
|
|
||
входной символ – В, сдвиг в состояние |
real |
|
|
1 |
|
|
3; |
|
|
3 |
|
||
|
|
В |
|
|
|
|
|
|
|
|
6 |
|
|
real A, B, C ^ |
|
, |
|
|
5 |
|
|
|
IDLIST |
|
|
2 |
|
|
|
real |
|
|
1 |
|
входной символ – «,», приведение по правилу (4); |
|
|
6 |
|
||
|
|
|
|
|
|
|
real A, B, C ^ |
|
, |
|
|
5 |
|
|
IDLIST |
|
|
2 |
|
|
|
|
|
|
|
||
|
|
real |
|
|
1 |
|
входной символ – ID, сдвиг в состояние 7; |
|
|
7 |
|
||
|
|
ID |
|
|
|
|
|
|
|
|
6 |
|
|
real A, B, C ^ |
|
, |
|
|
5 |
|
|
|
IDLIST |
|
|
2 |
|
|
|
real |
|
|
1 |
|
входной символ – «,», приведение по правилу (2); |
|
|
2 |
|
||
real A, B, C ^ |
|
|
|
|
|
|
|
real |
|
|
1 |
|
|
входной символ – IDLIST, сдвиг в |
|
|
|
|||
состояние 5; |
|
|
5 |
|
||
|
|
IDLIST |
|
|
|
|
real A, B, C ^ |
|
|
|
2 |
|
|
|
|
real |
|
|
1 |
|
входной символ – «,», сдвиг в состояние 6; |
|
|
6 |
|
||
|
|
|
|
|
|
|
real A, B, C ^ |
|
, |
|
|
5 |
|
|
IDLIST |
|
|
2 |
|
|
|
|
|
|
|
||
|
|
real |
|
|
1 |
|
входной символ – С, сдвиг в состояние |
3; |
|
|
3 |
|
|
|
|
С |
|
|
|
|
|
|
|
|
6 |
|
|
real A, B, C ^ |
|
, |
|
|
5 |
|
|
|
IDLIST |
|
|
2 |
|
|
|
real |
|
|
1 |
|
|
96 |
|
|
|
|
входной символ – «^», приведение по правилу (4); |
|
6 |
|
||
|
|
|
|
|
|
real A, B, C ^ |
|
, |
|
5 |
|
|
IDLIST |
|
2 |
|
|
|
|
|
|
||
|
|
real |
|
1 |
|
входной символ – ID, сдвиг в состояние 7; |
|
7 |
|
||
|
|
ID |
|
|
|
|
|
|
6 |
|
|
real A, B, C ^ |
|
, |
|
5 |
|
|
|
IDLIST |
|
2 |
|
|
|
real |
|
1 |
|
входной символ – «^», приведение по правилу (2); |
|
2 |
|
||
real A, B, C ^ |
|
|
|
|
|
|
real |
|
1 |
|
|
входной символ – IDLIST, сдвиг в |
|
|
|||
состояние 5; |
|
5 |
|
||
|
|
IDLIST |
|
|
|
real A, B, C ^ |
|
|
2 |
|
|
|
|
real |
|
1 |
|
входной символ – «^», приведение по правилу (1); |
|
1 |
|
||
real A, B, C ^ |
|
|
|
|
входной символ – S, поэтому HALT (ОСТАНОВ). Разбор завершен успешно.
Заметим, что после сдвига входным символом является следующий символ, а после приведения – символ, к которому только что привело действие.
5.3. Построение LR – таблицы разбора
При построении LR-таблиц разбора нам необходимо ссылаться на конкретную позицию в правиле, поэтому в правилах вводится понятие «конфигурация». Например, в грамматике
1)S ® · real IDLIST
2)IDLIST ® IDLIST, ID
3)IDLIST ® ID
4)ID ® A | B | C |D
точка соответствует конфигурации(1,0), т.е. правило 1) позиция 0; конфигурация (1,1) соответствует точке, появляющейся сразу после real в правиле 1), а (2,0) – точке появляющейся перед IDLIST в правой части правила 2). Так, конфигурация (2,2) показывает, что правая часть правила 2) распознана по запятую включительно.
97
Состояние в таблице разбора примерно соответствует конфигурациям в грамматике с той разницей, что конфигурации, которые неразличимы для анализатора, представляются одним и тем же состоянием. Например, если (1,0) соответствует состоянию 1, а (1,1) - состоянию 2, то в вышеприведенной грамматике (2,0), (3,0) и (4,0) будут также соответствовать состоянию 2. В этом случае говорят, что множество кон-
фигураций
{(1,1), (2,0), (3,0), (4,0)}
образуют замыкание (1,1).
Из заданного состояния, не соответствующего концу правила, можно перейти в другое состояние, введя терминальный или нетерминальный символ. Это состояние называетсяпреемником первоначального состояния. Чтобы построить таблицу разбора, необходимо прежде найти все состояния в грамматике. Поэтому, начиная с конфигурации (1,0), последовательно выполним операции замыкания и образования приемника до тех пор, пока все конфигурации не окажутся включенными в какое-либо состояние. Там, где ряд конфигураций содержится в одном замыкании, каждая из них будет соответствовать одному и тому же состоянию. Новая конфигурация, которая получается при операции образования преемника, называется базовой. Если за базовой конфигурацией следует нетерминал, то все конфигурации, соответствующие помещению точки слева от каждой правой части для данного нетерминала, сконцентрируются в замыкании этой базовой конфигурации. В приведенной грамматике можно выделить семь состояний, которые описываются следующим образом (табл. 5.2).
Таблица 5.2 – Состояния грамматики
Состояние |
База |
Замыкание |
1 |
(1,0) |
{(1,0)} |
2 |
(1,1) |
{(1,1), (2,0), (3,0), (4,0)} |
3 |
(4,1) |
{(4,1)} |
4 |
(3,1) |
{(3,1)} |
5 |
{(2,1), (1,2)} |
{(2,1), (1,2)} |
6 |
(2,2) |
{(2,2), (4,0)} |
7 |
(2,3) |
{(2,3)} |
Эти состояния расположены в грамматике следующим образом:
1)S ® 1 real 2 IDLIST 5
2)IDLIST ® 2 IDLIST 5 , 6 ID 7
3)IDLIST ® 2 ID 4
4)ID ® (2,6) A | B | C |D 3
98
Заметим, что конфигурация может соответствовать более чем -од ному состоянию, и в базе может быть более одной конфигурации, если преемники двух конфигураций в одном и том же замыкании неразличимы. Например, за конфигурациями (1,1) и (2,0) следует IDLIST, что делает (1,2) и (2,1) неразличимыми, пока не осуществится операция замыкания. Число состояний в анализаторе соответствует числу множеств неразличимых конфигураций в грамматике. Причина того, что два и более состояния соответствуют одной конфигурации, раскрывается в ходе разбора.
Действия анализатора со сдвигом аналогичны операции получения преемника. Поэтому действия со сдвигом в таблицу разбора могут вноситься на основании информации о размещении состояний в грамматике (табл. 5.3).
Таблица 5.3.
Состояние |
S |
IDLIST |
ID |
real |
«,» |
A |
^ |
|
|
|
|
|
|
B |
|
|
|
|
|
|
|
C |
|
|
|
|
|
|
|
D |
|
1 |
|
S5 |
S4 |
S2 |
|
S3 |
|
2 |
|
|
|
|
|||
3 |
|
|
|
|
|
|
|
4 |
|
|
|
|
S6 |
|
|
5 |
|
|
|
|
S3 |
|
|
6 |
|
|
|
|
|
|
|
7 |
|
|
|
|
|
|
|
Например, правило 2) означает «из состояния 2 при чтении IDLIST перейти в состояние 5», «из состояния 5 при чтении запятой перейти в состояние 6» и т.д.
Задача внесения приведения в таблицу разбора нетривиальна. Однако, единственные состояния, в которых приведения возможны, - это состояния, соответствующие окончаниям правил (в нашей грамматике 3, 4, 5, и 7). Поэтому мы можем внести R4 во все столбцы состояния 3, R3 - во все столбцы состояния 4, R1 – во все столбцы состояния 5 и R2
– во все столбцы состояния7. Однако в состоянии 5 в одном столбце уже имеется элемент сдвига. Таким образом, возникает конфликт сдвиг/приведение. Состояние 5 называется неадекватным. Разрешить эту проблему можно просматривая символы, которые показали бы приведение в состояние 5, а не сдвиг. Из правил 1) и 2) следует, что такими символами могут быть только «^» и «,», а приведение возможно лишь в том случае, если символ окажется «^», в то время как анализатор осуществит сдвиг в состояние6, если следующим символом