Общая схема работы компилятора

 

Схема работы компилятора

 

На рис. 1 представлена общая схема работы компилятора. Видно, что в целом процесс компиляции состоит из двух основных этапов – синтеза и анализа.

На этапе анализа выполняется распознавание текста исходной программы, соз­дание и заполнение таблиц идентификаторов. Результатом его работы служит некое внутреннее представление программы, понятное компилятору.

На этапе синтеза на основании внутреннего представления программы и информации, содержащейся в таблице (таблицах) идентификаторов, порождается текст результирующей программы. Результатом этого этапа является объектный код.

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

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

Рис. 1. Общая схема работы компилятора

 

Компилятор в целом с точки зрения теории формальных языков выполняет две основные функции.

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

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

Рассмотрим основные фазы компиляции.

Лексический анализ (сканер) – это часть компилятора, которая читает литеры программы на исходном языке и строит из них слова (лексемы) исходного язы­ка. На вход лексического анализатора поступает текст исходной программы, а выходная информация передается для дальнейшей обработки компилятором на этапе синтаксического разбора.

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

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

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

Генерация кода – это фаза, непосредственно связанная с порождением команд, составляющих предложения выходного языка и в целом текст результирующей программы. Это основная фаза на этапе синтеза результирующей программы. Кроме непосредственного порождения текста результирующей программы, гене­рация обычно включает в себя также оптимизацию – процесс, связанный с обра­боткой уже порожденного текста. Иногда оптимизацию выделяют в отдельную фазу компиляции, так как она оказывает существенное влияние на качество и эффективность результирующей программы.

Таблицы идентификаторов (иногда – “таблицы символов”) – это специальным образом организованные наборы данных, служащие для хранения информации об элементах исходной программы, которые затем используются для порожде­ния текста результирующей программы. Таблица идентификаторов в конкрет­ной реализации компилятора может быть одна или же таких таблиц может быть несколько. Элементами исходной программы, информацию о которых нужно хра­нить в процессе компиляции, являются переменные, константы, функции и т. п. – конкретный состав набора элементов зависит от используемого входного языка программирования. Понятие “таблицы” вовсе не предполагает, что это хранилище данных должно быть организовано именно в виде таблиц или других массивов информации.

 

Понятие прохода.