Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции кошкин.doc
Скачиваний:
4
Добавлен:
01.03.2025
Размер:
667.65 Кб
Скачать

(2 )Варианты построения макропроцессоров.

Различают две группы: 1) макропроцессоры общего применения. 2) специализированные макропроцессоры. Первая группа не зависит от конкретно языка программирования, поэтому они могут использоваться различными языками. Преимущество макропроцессоров общего применения – программист не должен изучать все специализированные средства. Универсальные языки позволяют быстрее освоится, сократить время разработки и сопровождения программ. Понятно, что любые универсальные средства по структуре и объему больше специализированных. Они дороже, но первоначальные затраты на разработку могут быть скомпенсированы за счет экономии на сопровождении. Не смотря не такое преимущество вариантов макропроцессоров общего назначения немного. Универсальность таких программ заставляет учитывать многие детали и усложняет разработку.

При работе с обычными языками некоторые записи не должны транслироваться, например, комментарии. Поэтому, в языках предусматриваются специальные символы, указывающие макропроцессору на то, что последующая запись не должна обрабатываться. Также между языками имеется различие со средствами группирования символов. Часто используют скобки и задача макропроцессора определить такие средства. Более общая проблема встает при анализе записей. Макропроцессор должен различать пробелы, запись одного предложения в специальных строках, специальное соглашение на форматирование. Макропроцессоры специализированные, обычно встраивают в трансляторы. Простейший способ реализации функции макропроцессора самим транслятором, использование подхода строка за строкой. Макропроцессор читает предложение исходной программы и выполняет макроинициализацию. Генерирует расширенную версию программы. По мере того, как генерируются строки, они передаются одна за другой на другой вход транслятора. Т.е. макропроцессор работает подобно ассемблеру. В этом случае не нужен дополнительный проход по программам. Некоторые таблицы, используемые самими макропроцессорами и транслятором содержаться в единственном числе. При трансляции могут быть использованы и некоторые другие функции: поиск по таблице, преобразование числовых констант, элементы диагностики. Хотя макропроцессор, реализующий принцип строка за строкой, использует те же таблицы, что и транслятор, основные функции их различны. Во встроенных макропроцессорах можно использовать любую информацию об исходной программе имеющуюся у транслятора. Т.е. не нужно дополнительных программных средств макропроцессора, он их заимствует у транслятора. Имеется ряд недостатков у встроенных макропроцессоров: такая программа более тесно связана с транслятором и не может работать с другими его версиями. Стоимость разработки программы транслятора увеличивается за счет макропроцессора. В целом программа сложнее, занимает больше места. Поэтому выбор макропроцессора общего применения или специализированного проводится с учетом указанных достоинств и недостатков обоих программ.

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

Компиляторы — программные средства преобразования текста программ с языков высокого уровня в машинные языки. Транслятор — второй термин используемый для этих же задач. Задача компиляции — это поиски соответствия написанных программистом предложений определенным структурам, грамматике и генерация машинного кода. Основную задачу компиляторов можно определить как замену переменных, написанных программистом согласно правил грамматики на последовательность машинных кодов, которые являются программой (кодами команд, данными, служебными словами). Для облегчения построения компиляторов язык описывается в терминах некоторой грамматики, она определяет синтаксис конструкций предложений (язык). Предложение исходной программы удобнее представлять в виде последовательности лексем, а не рассматривать просто как строку символов. Каждая написанная строка состоит из последовательности «кирпичиков» — стандартных наборов символов. Эти наборы называют лексемами. Количество символов в лексеме от одного и больше. Просмотр исходного текста, распознавание лексем и их классификация называется лексическим анализом. Первая составляющая компиляторов — лексические анализаторы. Как только лексемы узнаны, нужно распознать конструкции языка (комбинации лексем) — это выполняет синтаксический анализатор. Третий, последний шаг — генерация объектного кода. Таким образом, компилятор должен выполнить три основных шага: лексический анализ, синтаксический анализ, генерацию кода. В процессе выполнения этих функций результат может быть получен за один или несколько проходов.

Грамматика является формальным описанием языка программирования. Существует несколько форм представления грамматики. Форма Бекуса-Наура (БНФ) широко используется. Грамматика типа БНФ включает множество правил выбора, каждое правило определяет синтаксис конструкции языка. Результат анализа исходного предложения представляют в виде дерева (дерева грамматического разбора или синтаксическое дерево). В каждой команде выделяются лексемы и располагаются в логической последовательности. Встречается грамматика, согласно правилам которой можно построить для конкретного фрагмента не одно дерево. При разработке компиляторов отдают предпочтение однозначным грамматикам, т. е. тем, по которым вариант дерева только один.

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

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

  1. нисходящие методы

  2. восходящие методы

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

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

Пример нисходящего метода: рекурсивный спуск.

Последний шаг компиляции — генерация объектного кода. С этой целью необходим набор подпрограмм, каждая из которых обслуживает соответствующие правила грамматики. Как только в результате грамматического разбора будет распознан объект текста, соответствующий правилам грамматики, вызывается подпрограмма этого правила и формируется массив кодов. Иногда эти подпрограммы могут формировать результирующий код сразу, либо через промежуточную форму (2 прохода). Генерируемый код во многом зависит от типа ЭВМ для которой пишется программа. Т. е. компилятор одного языка для разных типов программ должен сгенерировать различные машинные коды.