- •Теория вычислительных процессов и структур
 - •1. Предварительные математические сведения
 - •1.2. Операции над множествами Объединение множеств
 - •Пересечение множеств
 - •Разность множеств
 - •1.3. Множества цепочек
 - •1.4. Языки
 - •1.5. Алгоритмы
 - •1.6. Некоторые понятия теории графов
 - •2. Введение в компиляцию
 - •2.1. Задание языков программирования
 - •2.2. Синтаксис и семантика
 - •2.3. Процесс компиляции
 - •2.4. Лексический анализ
 - •2.5. Работа с таблицами
 - •2.6. Синтаксический анализ
 - •2.7. Генератор кода
 - •Алгоритм.
 - •2.8. Оптимизация кода
 - •2.9. Исправление ошибок
 - •2.10. Резюме
 - •3. Теория языков
 - •3.1. Способы определения языков
 - •3.2. Грамматики
 - •Пример.
 - •3.3. Грамматики с ограничениями на правила
 - •3.4. Распознаватели
 - •3.5. Регулярные множества, их распознавание
 - •3.6. Регулярные множества и конечные автоматы
 - •3.7. Графическое представление конечных автоматов
 - •3.8. Конечные автоматы и регулярные множества
 - •3.9. Минимизация конечных автоматов
 - •3.10. Контекстно-свободные языки
 - •3.10.1. Деревья выводов
 - •3.10.2. Преобразование кс–грамматик
 - •3.10.3. Грамматика без циклов
 - •3.10.4. Нормальная форма Хомского
 - •3.10.5. Нормальная формула Грейбах
 - •3.11. Автоматы с магазинной памятью
 - •3.11.1. Основные определения
 - •3.11.2. Эквивалентность мп-автоматов и кс-грамматик
 - •4.1. Эквивалентность мп-автоматов и кс-грамматик
 - •4.2. Ll(1)-грамматики
 - •4.3. Ll(1)-таблица разбора
 - •5. Синтаксический анализ снизу вверх
 - •5.1. Разбор снизу вверх
 - •5.2. Lr(1) - таблица разбора
 - •5.3. Построение lr – таблицы разбора
 - •5.4. Сравнение ll – и lr – методов разбора
 - •6. Включение действий в синтаксис
 - •6.1. Получение четверок
 - •6.2. Работа с таблицей символов
 - •7. Проектирование компиляторов
 - •7.1. Число проходов
 - •7.2. Таблицы символов
 - •Identifier, type.
 - •Int procedure rehash(int n)
 - •Int procedure rehash(int n)
 - •7.3. Таблица видов
 - •8. Распределение памяти
 - •8.1. Стек времени прогона
 - •Integer a, b, X, y
 - •Int table[1:10, -5:5].
 - •8.2. Методы вызова параметров
 - •8.3. Обстановка выполнения процедур
 - •8.4. «Куча»
 - •8.5. Счетчик ссылок
 - •8.6. Сборка мусора
 - •9. Генерация кода
 - •(Тип – адреса, номер - блока, смещение).
 - •9.2. Структура данных для генерации кода
 - •9.3. Генерация кода для типичных конструкций
 - •9.3.1. Присвоение
 - •9.3.2. Условные зависимости
 - •If b then c else d
 - •9.3.3. Описание идентификаторов
 - •9.3.4. Циклы
 - •9.3.5. Вход и выход из блока
 - •9.3.6. Прикладные реализации
 - •9.4. Проблемы, связанные с типами
 - •9.5. Время компиляции и время прогона
 - •10. Исправление и диагностика ошибок
 - •10.1. Типы ошибок
 - •10.2. Лексические ошибки
 - •10.3. Ошибки в употреблении скобок
 - •Begin end
 - •Case esac
 - •10.4. Синтаксические ошибки
 - •10.5. Методы исправления синтаксических ошибок
 - •End begin
 - •10.6. Предупреждения
 - •10.7. Сообщения о синтаксических ошибках
 - •10.8. Контекстно-зависимые ошибки
 - •Identifier xyz not declared
 - •Identifier blank alredy declared in block
 - •10.9. Ошибки, связанные с употреблением типов
 - •Int I; char c;
 - •10.10. Ошибки, допускаемые во время прогона
 - •10.11. Ошибки, связанные с нарушением ограничений
 
5.4. Сравнение ll – и lr – методов разбора
Как LL - , так иLR – методы разбора имеют много достоинств. Оба метода – детерминированы и могут обнаруживать синтаксические ошибки на самом раннем этапе.LR – методы обладают тем преимуществом, что они применимы к более широкому классу грамматик и языков и преобразование грамматик в них обычно не требуется. Однако, для хорошо структурированной грамматики сам факт преобразования грамматики не вызывает каких-либо технических трудностей.
Два этих метода можно сравнивать в отношении размеров таблиц разбора и времени разбора. Использование по одному слову на элемент в LL– таблице разбора позволяет свести размер типичной таблицы к минимуму, в то время какLR– разбор этой возможности не предоставляет.
Коэн и Рот сравнивали максимальное и среднее время разбора с помощью LL – иLR– анализаторов. Из данных для машин серииDECрезультаты разбораLL– методом оказались быстрее на 50%.
Оба метода разбора позволяют включать в синтаксис действия для выполнения некоторых аспектов компиляции. Для LR– анализаторов такие действия обычно связаны с приведениями.
Разные разработчики компиляторов отдают предпочтение разным методам (т.е. разбору снизу вверх или сверху вниз), что постоянно служит предметом дискуссий. На практике выбор метода в основном зависит от наличия хорошего генератора синтаксических анализаторов любого типа.
Контрольные вопросы
Технология разбора снизу вверх.
Построение LR – таблицы разбора.
Метод определения количества состояний грамматики.
Разрешение конфликта сдвиг/приведение.
Сравнение LL - и LR – методов разбора.
6. Включение действий в синтаксис
Синтаксический анализ и генерация кода принципиально различные процессы, но практически во всех компиляторах они выполняются параллельно (т.е. генерация кода осуществляется параллельно с синтаксическим анализом). Наша задача – рассмотреть возможность включения в систему синтаксического анализа действий для генерации кода.
6.1. Получение четверок
В качестве примера включения действия в грамматику для генерирования кода рассмотрим проблему разложения арифметических выражений на четверки. Выражения определяются грамматикой со следующими правилами:

Таким образом, эти правила позволяют анализировать выражения типа:

Грамматика для четверок имеет следующие правила:

Примеры четверок:

Выражение
![]()
будет соответствовать последовательности четверок:

Целые числа с левой стороны от знаков равенства относятся к другим четверкам. Из сформулированных четверок нетрудно генерировать машинный код, а многие компиляторы на основании четверок осуществляют трансляцию в промежуточный код.
Далее для описания общей схемы разбора примем следующие обозначения: действия заключаются в угловые скобки и обозначаются как А1, А2…Для реализации алгоритма четверок требуется четыре действия. Алгоритм пользуется стеком, а номера четверок размещаются с помощью целочисленной переменной. Перечислим эти действия:
А1 – поместить элемент в стек;
А2 – взять три элемента из стека, напечатать их с последующим знаком «=» и номером следующей размещаемой четверки и поместить полученное целое число в стек;
А3 –взять два элемента из стека, напечатать их с последующим значением «=» и номером следующей размещаемой четверки и поместить полученное целое в стек;
А4 –взять из стека один элемент.
Грамматика с учетом этих добавлений примет вид

Действие А1используется для помещения в стек всех идентификаторов и операторов, а действияА2 иА3– для получения бинарных и унарных четверок соответственно.
В качестве примера проследим за преобразованием выражения
![]()
в четверки. Действие А1 выполняется после распознавания каждого идентификатора и оператора, действиеА2 – после второго операнда каждого знака бинарной операции, а действиеА3– после первого (и единственного) оператора каждой унарной операции. ДействиеА4выполняется только один раз после считывания всего выражения.
| 
			 Последняя считанная литера  | 
			 Действие  | 
			 Выход  | 
| 
			 ( - а 
 
 + b 
 
 )  ( с + d 
 
 ) 
  | 
			 - А1, поместить в стек «-» А1, поместить в стека А3,удалить из стека 2 элемента Поместить в стек «1» А1, поместить в стек «+» А1, поместить в стекb А2, удалить из стека 3 элемента Поместить в стек «2» - А1, поместить в стек «» - А1, поместить в стекс А1, поместить в стек «+» А1, поместить в стекd А2, удалить из стека 3 элемента Поместить в стек «3» - А2, удалить из стека 3 элемента Поместить в стек «4» А4, удалить из стека 1 элемент  | 
			 
 
 
 -а=1 
 
 
 1+b=2 
 
 
 
 
 
 
 c+d=3 
 
 23=4 
  | 
В рассматриваемом примере нам не пришлось сравнивать приоритеты двух операций, так как эти приоритеты уже заложены в правилах грамматики.
