Читайте также:
|
|
Зачастую фазы объединяются в начальную (front end) и заключительную (back end) стадии. Начальная стадия объединяет те фазы компилятора (или части фаз), которые зависят в первую очередь от исходного языка и практически не зависят от целевой машины. Обычно сюда входят лексический и синтаксический анализ, создание таблицы символов, семантический анализ и генерация промежуточного кода. На этом этапе может быть выполнена и определенная часть оптимизации кода. Кроме того, начальная стадия включает обработку ошибок, которая сопровождает каждую фазу компилятора.
Заключительная стадия состоит из тех фаз компилятора, которые в первую очередь зависят от целевой машины, для которой выполняется компиляция, и, вообще говоря, не зависят от исходного языка (а только от промежуточного). Кроме того, сюда входит часть оптимизации кода и генерация выходного кода, сопровождаемые необходимой обработкой ошибок и работой с таблицей символов.
Таким образом, создание компиляторов одного и того же исходного языка для различных машин является достаточно простой операцией. При этом можно использовать одну и ту же начальную стадию, не зависящую от целевой машины. Более того, при умелой разработке заключительной стадии не потребуется даже внесение существенных изменений в нее (см. главу 9, "Генерация кода"). Соблазнительно также компилировать различные исходные языки в один промежуточный и использовать общую заключительную стадию для разных предварительных стадий, получая тем самым ряд компиляторов для различных языков с одной целевой машиной. Однако в данном случае успех не гарантирован из-за множества нюансов в различных языках программирования.
Проходы
Обычно фазы компиляции реализуются в одном проходе (pass), состоящем из чтения входного файла и записи выходного. Имеется множество способов группировки фаз компилятора по проходам, и поэтому рассмотрение процесса компиляции в данной книге в большей степени привязано к фазам, а не проходам. В главе 12, "Некоторые компиляторы" будут рассмотрены некоторые типичные компиляторы и способы распределения фаз компиляции по проходам.
Как упоминалось, группирование нескольких фаз в одном проходе широко распространено; их выполнение чередуется во время прохода. Например, лексический, синтаксический и семантический анализы, а также генерация промежуточного кода могут быть сгруппированы в одном проходе. В этом случае поток токенов после лексического анализа может быть транслирован непосредственно в промежуточный код. Синтаксический анализ можно рассматривать как "руководящий" процесс. Он получает поток токенов с помощью вызова лексического анализатора для получения следующего токена в потоке. После того как определена грамматическая структура, синтаксический анализатор вызывает генератор промежуточного кода для семантического анализа и генерации части кода. Такой компилятор описан в главе 2, "Простой однопроходный компилятор".
Дата добавления: 2015-11-30; просмотров: 38 | Нарушение авторских прав