Что такое дизайн компилятора? Типы, Строительные инструменты, Пример
⚡ Умное резюме
В разделе «Фазы компиляции» описываются шесть этапов преобразования исходного кода в машинный код: лексический анализ, синтаксический анализ, семантический анализ, генерация промежуточного кода, оптимизация кода и генерация кода, поддерживаемая управлением таблицами символов и обработкой ошибок.
Каковы этапы разработки компилятора?
A составитель Компилятор работает в несколько этапов, и каждый этап преобразует исходную программу из одного представления в другое. Каждый этап принимает входные данные с предыдущего этапа и передает свои выходные данные на следующий этап компилятора. В компиляторе 6 этапов. Каждый из этих этапов помогает преобразовать язык высокого уровня в машинный код. Этапы компилятора:
- Лексический анализ
- Синтаксический анализ
- Семантический анализ
- Генератор промежуточного кода
- Code оптимизатор
- Code генератор
Фазы компилятора
На всех этих этапах исходный код преобразуется путем разделения его на токены, создания деревьев разбора и оптимизации исходного кода на разных этапах.
Этап 1: Лексический анализ
Лексический анализ — это первый этап, когда компилятор сканирует исходный код. Этот процесс может происходить слева направо, посимвольно, и группирует эти символы в токены.
Здесь поток символов из исходной программы группируется в осмысленные последовательности путем идентификации токенов. Соответствующие токены вносятся в таблицу символов, и этот токен передается на следующий этап.
Основными функциями этого этапа являются:
- Определите лексические единицы в исходном коде.
- Классифицируйте лексические единицы по классам, таким как константы, зарезервированные слова, и внесите их в разные таблицы. Комментарии в исходном коде программы будут игнорироваться.
- Определите токен, который не является частью языка.
Пример: х = у + 10
| Токены | Тип |
|---|---|
| X | идентификатор |
| = | Оператор присваивания |
| Y | идентификатор |
| + | Оператор сложения |
| 10 | Номер регистрации |
Этап 2: Синтаксический анализ
Синтаксический анализ — это выявление структуры в коде. Он определяет, соответствует ли текст ожидаемому формату. Главная цель этого этапа — убедиться в корректности исходного кода, написанного программистом.
Синтаксический анализ основан на правилах конкретного языка программирования и строит дерево разбора с помощью токенов. Он также определяет структуру исходного языка и его грамматику или синтаксис.
Вот список задач, выполняемых на этом этапе:
- Получите токены из лексического анализатора.
- Проверьте, является ли выражение синтаксически корректным.
- Сообщайте обо всех синтаксических ошибках.
- Создайте иерархическую структуру, известную как дерево разбора.
Пример
Любой идентификатор/число является выражением. Если x — идентификатор, а y+10 — выражение, то x = y+10 — это утверждение. Рассмотрим дерево разбора для следующего примера:
(a+b)*c
В дереве разбора:
- Внутренний узел: запись с полем оператора и двумя полями для дочерних элементов.
- Листовые записи: записи, содержащие 2 или более полей; одно для токена, а другое — для информации о токене.
- Убедитесь, что компоненты программы осмысленно взаимодействуют друг с другом.
- Собирает информацию о типах и проверяет их совместимость.
- Операнды проверки разрешены исходным языком.
Этап 3: Семантический анализ
Семантический анализ проверяет семантическую согласованность кода. Он использует синтаксическое дерево предыдущего этапа вместе с таблицей символов для проверки семантической согласованности данного исходного кода. Он также проверяет, передает ли код соответствующее значение.
Семантический анализатор проверит наличие несоответствий типов, несовместимых операндов, вызова функции с некорректными аргументами, необъявленной переменной и т. д.
Функции этапа семантического анализа включают в себя:
- Помогает сохранять собранную информацию о типах и регистрировать её в таблице символов или синтаксическом дереве.
- Позволяет выполнять проверку типов.
- В случае несоответствия типов, когда отсутствуют точные правила коррекции типов, удовлетворяющие требуемой операции, отображается семантическая ошибка.
- Собирает информацию о типах и проверяет их совместимость.
- Проверяет, допускает ли исходный язык эти операнды.
Пример
float x = 20.2; float y = x*30;
В приведенном выше коде семантический анализатор преобразует целое число 30 в число с плавающей запятой 30.0 перед умножением.
Фаза 4: Промежуточная Code Поколение
После завершения этапа семантического анализа компилятор генерирует промежуточный код для целевой машины. Он представляет собой программу для некоторого абстрактного типа данных.tracмашина Т.
Промежуточный код находится между языком высокого уровня и машинным языком. Этот промежуточный код необходимо генерировать таким образом, чтобы его было легко преобразовать в целевой машинный код.
Функции промежуточного Code поколение:
- Оно должно быть сгенерировано на основе семантического представления исходной программы.
- Содержит значения, вычисленные в процессе перевода.
- Помогает перевести промежуточный код на целевой язык.
- Позволяет сохранить порядок приоритета исходного языка.
- В нем содержится правильное количество операндов инструкции.
Пример
Например:
total = count + rate * 5
Промежуточный код, полученный с помощью метода адресного кода, выглядит следующим образом:
t1 := int_to_float(5)
t2 := rate * t1
t3 := count + t2
total := t3
Фаза 5: Code Оптимизация
Следующий этап — оптимизация промежуточного кода. На этом этапе удаляются ненужные строки кода и упорядочивается последовательность операторов для ускорения выполнения программы без нерационального использования ресурсов. Главная цель этого этапа — улучшить промежуточный код, чтобы получить код, который работает быстрее и занимает меньше места.
Основными функциями этого этапа являются:
- Это помогает установить компромисс между скоростью выполнения и скоростью компиляции.
- Улучшает время выполнения целевой программы.
- Генерирует упрощенный код, находящийся в промежуточном представлении.
- Удаление недоступного кода и избавление от неиспользуемых переменных.
- Удаление операторов, которые не были изменены в цикле.
Пример: Рассмотрим следующий код:
a = intofloat(10)
b = c * a
d = e + b
f = d
Может стать:
b = c * 10.0
f = e + b
Фаза 6: Code Поколение
Code Генерация — это последняя и заключительная фаза компилятора. Она получает входные данные из фазы оптимизации кода и в результате генерирует страничный код или объектный код. Цель этой фазы — выделить память и сгенерировать перемещаемый машинный код.
Также выделяются ячейки памяти для переменных. Инструкции в промежуточном коде преобразуются в машинные инструкции. На этом этапе оптимизированный или промежуточный код преобразуется в целевой язык.
Целевым языком является машинный код. Поэтому на этом этапе также выбираются и выделяются все ячейки памяти и регистры. Сгенерированный на этом этапе код выполняется для приема входных данных и генерации ожидаемых выходных данных.
Пример
a = b + 60.0 можно было бы перевести в регистры следующим образом:
MOVF a, R1 MULF #60.0, R2 ADDF R1, R2
Управление таблицей символов
Таблица символов содержит запись для каждого идентификатора с полями, описывающими атрибуты идентификатора. Этот компонент упрощает компилятору поиск записи идентификатора и позволяет быстро её получить. Таблица символов также помогает в управлении областью видимости. Таблица символов и обработчик ошибок взаимодействуют со всеми этапами, и таблица символов обновляется соответствующим образом.
Процедура обработки ошибок
В процессе проектирования компилятора ошибки могут возникать на всех нижеперечисленных этапах:
- Лексический анализатор: Неправильно написанное слово tokens.
- Синтаксический анализатор: Отсутствует скобка.
- Генератор промежуточного кода: Несоответствие операндов для оператора.
- Code Оптимизатор: Когда запрос недоступен.
- Code Generator: Когда память заполнена или не выделены необходимые регистры.
- Таблицы символов: Ошибка, связанная с множественным объявлением идентификаторов.
Наиболее распространенными ошибками являются недопустимые последовательности символов при сканировании, недопустимые последовательности токенов при вводе, ошибки области видимости и ошибки синтаксического анализа.
Ошибка может возникнуть на любом из вышеописанных этапов. После обнаружения ошибок, на следующем этапе необходимо обработать их, чтобы продолжить процесс компиляции. Эти ошибки необходимо передать обработчику ошибок, который обрабатывает их для выполнения процесса компиляции. Как правило, ошибки сообщаются в виде сообщения.



