Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Полный файл лекции Иванченко.DOC
Скачиваний:
17
Добавлен:
21.09.2019
Размер:
2.42 Mб
Скачать

Глава 6 основы генерации кода

6.1. Перевод и генерация кода

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

Выбор того, что назвать фазой, достаточно произволен. Удобно считать основными фазами компиляции лексический анализ, синтаксический анализ и генерацию кода.

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

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

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

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

Компилятор должен проверять, соблюдены ли определенные семантические соглашения входного языка, например :

а) каждая метка, используемая в операторе GOTO, должна обязательно появиться в качестве метки некоторого оператора в исходной программе ;

б) никакой идентификатор не может быть описан более одного раза ;

в) все переменные должны объявляться перед использованием ;

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

После синтаксического анализа промежуточная программа отображается генератором кода в объектную программу. В процессе генерации кода используется информация из таблицы имен для того, чтобы правильно выбрать последовательность команд (например, код для А+В зависит от типа переменных А и В, а информация о типе находится в таблице имен ) и правильно распределить память (т. е. выяснить, является переменная скаляром или структурированным объектом ).

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