1.11.3. ОБЩАЯ СТРУКТУРА КОМПИЛЯТОРА

Наш компилятор имеет "классическую" структуру и состоит из следующих частей.

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

Затем поток лексем попадает в синтаксический анализатор, который превращает этот поток в дерево синтаксического разбора, которое часто называют также программой, записанной в абстрактном синтаксисе, или абстрактной программой.

Далее абстрактная программа попадает в генератор кода, результатом работы которого является программа на языке ассемблера. Ассемблерная программа, по сути, является уже почти готовой программой в машинном коде, однако, вместо конкретных адресов ячеек она содержит метки, каждая из которых изображает некоторый еще неизвестный адрес.

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

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

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