Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СПО ЛЕКЦИИ.docx
Скачиваний:
25
Добавлен:
27.09.2019
Размер:
160.65 Кб
Скачать

2.1.3. Интерпретаторы

Еще одним средством восприятия программы на исходном языке является интерпретатор, который тоже является программой.

Само слово интерпретация – это реализация смысла некоторого синтаксически законченного текста, представленного на конкретном языке.

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

Интерпретатор принципиально отличается от схожих между собой понятий «транслятор» и «компилятор».

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

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

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

Рассмотрим схему работы транслятора на примере компилятора, как более глубокой формы транслятора. Структура и схема работы компилятора приведена на рис. 2.1.

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

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

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

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

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

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

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

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

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

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

Лексический анализ выполняется лексическим анализатором (сканером), он служит для построения слов исходного языка (лексем), которые в дальнейшем используются при синтаксическом анализе. С теоретической точки зрения сканер не является обязательной, необходимой частью компилятора, т. к. все его функции могут выполняться на этапе синтаксического разбора, поскольку полностью регламентированы синтаксисом входного языка. Однако практически во всех компиляторах он присутствует. Для этого имеются три причины:

– применение сканера упрощает работу и сокращает объем обрабатываемой информации на этапе синтаксического разбора, т. к. он структурирует исходный текст и обрабатывает всю незначащую информацию;

– сканер реализуется на основе простой, эффективной и теоретически хорошо проработанной технике анализа, в отличие от достаточно сложных алгоритмов синтаксического разбора, которые пришлось бы использовать для лексического анализа при отсутствии сканера;

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

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

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

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

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

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

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

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

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