
- •Вопрос 1 Трансляторы , интерпретаторы и компиляторы
- •Вопрос 2
- •Вопрос3 Понятие о грамматике языка
- •Вопрос 4
- •Вопрос 4 Способы задания схем грамматик
- •Вопрос 5 Классификация грамматик и языков по Хомскому (грамматики классифицируются по виду их правил вывода)
- •Вопрос 6 *каша* думайте сами что и куда писать
- •Вопрос 6. Парт 2 Разбор цепочек
- •Преобразования грамматик
- •Вопрос 7
- •Вопрос 8 Простейшие способы организации таблицы идентификаторов
- •Вопрос 9 Автоматные грамматики и конечные автоматы
- •Вопрос 10 Регулярные выражения. Свойства регулярных выражений
- •Вопрос 11
- •Вопрос 12.1.
- •Вопрос 12.2
- •1. Для каждой упорядоченной пары терминальных символов выполняется не более чем одно из трех отношений предшествования:
- •Вопрос 13
- •Вопрос 14
- •Вопрос 15
- •Вопрос 16
- •Вопрос 17
- •Вопрос 18
- •Вопрос 19
- •Вопрос 20 Распознаватель на основе алгоритма «сдвиг-свертка»
- •Вопрос 21 Метод рекурсивного спуска
- •Вопрос 22
- •Вопрос 23 внутренние формы представления программы
- •Вопрос 24 Оптимизация объектного кода методом свертки
- •Оптимизация объектного кода методом исключения лишних операций
- •Общий алгоритм генерации и оптимизации объектного кода
Вопрос 13
Синтаксический анализ - это процесс, в котором исследуется цепочка лексем и устанавливается, удовлетворяет ли она структурным условиям, явно сформулированным в определении синтаксиса языка. Это – самая сложная часть компилятора.
Синтаксический анализатор расчленяет исходную программу на составные части, формирует ее внутреннее представление, заносит информацию в таблицу символов и другие таблицы. При этом производится полный синтаксический и, по возможности, семантический контроль программы. Фактически, это - синтаксически управляемая программа. При этом обычно стремятся отделить синтаксис от семантики насколько это возможно - когда синтаксический анализатор распознает конструкцию исходного языка, он вызывает семантическую процедуру, которая контролирует эту конструкцию, заносит информацию куда надо, проверяет на дублирование описания переменных, проверяет соответствие типов и т.п.
Предложения исходной программы обычно записываются в инфиксной форме. Однако эта привычная форма, в которой оператор записывается между операндами, является совершенно не пригодной для автоматического вычисления. Дело в том, что необходимо постоянно помнить о приоритетах операторов, "забегая" при анализе выражения "вперед". К тому же очень усложняют жизнь применяемые скобки, определяющие очередность вычислений. Альтернативой инфиксной форме является польская форма записи (в честь польского математика Лукасевича): постфиксная и префиксная. Обычно под польской формой понимают именно постфиксную форму записи. Кроме того, используются и такие внутренние формы представления исходной программы, как дерево (синтаксическое) и тетрады.
Вопрос 14
Общие принципы работы табличных распознавателей
Табличные распознаватели используют для построения цепочки вывода КС-грамматики другие принципы, нежели МП-автоматы. Как и МП-автоматы, они получают на вход цепочку входных символов = a1a2…an, VT*, || = n, а построение вывода основывают на правилах заданной КС-грамматики G(VT,VN,P,S). Принцип их работы заключается в том, что искомая цепочка вывода строится не сразу — сначала на основе входной цепочки порождается некоторое промежуточное хранилище информации объема n*n (промежуточная таблица), а потом уже на его основе строится вывод.
Табличные алгоритмы обладают полиномиальными характеристиками требуемых вычислительных ресурсов в зависимости от длины входной цепочки. Для произвольной КС-грамматики G(VT,VN,P,S) время выполнения алгоритма Тэ имеет кубическую зависимость от длины входной цепочки, а необходимый объем памяти Мэ — квадратичную зависимость от длины входной цепочки: Тэ = О(n3) и Мэ = O(n2). Квадратичная зависимость объема необходимой памяти от длины входной цепочки напрямую связана с использованием промежуточного хранилища данных.
Табличные распознаватели универсальны — они могут быть использованы для распознавания цепочек, порожденных с помощью произвольной КС-грамматики (возможно, саму грамматику первоначально потребуется привести к заданному виду, но это не ограничивает универсальности алгоритмов). Кроме того, табличные распознаватели — это самые эффективные с точки зрения требуемых вычислительных ресурсов универсальные алгоритмы для распознавания цепочек КС-языков.
Хотя табличные распознаватели и являются самыми эффективными среди универсальных распознавателей, тем не менее они не находят широкого применения. Дело в том, что полиномиальная зависимость требуемых вычислительных ресурсов от длины входной цепочки символов является неудовлетворительной для компиляторов (длины входных цепочек — тысячи и десятки тысяч символов). Поэтому практически всегда используются не универсальные, а более узкие, специализированные алгоритмы распознавателей, которые имеют обычно линейную зависимость требуемых вычислительных ресурсов от длины входной цепочки символов К универсальным алгоритмам прибегают только тогда, когда специализированный распознаватель построить не удается.
Алгоритм Кока—Янгера—Касами
Алгоритм Кока—Янгера—Касами для заданной грамматики G(VT,VN,P,S) и цепочки входных символов , = a1a2…an, VT*, || = n строит таблицу Tn*n, такую, что AVN: AT[i,j], тогда и только тогда, если А+аi...ai+j-1. Таким образом, элементами таблицы Tn*n являются множества нетерминальных символов в алфавита VN.
Тогда существованию вывода S* соответствует условие ST[1,n].
При условии существования вывода по таблице Tn*n можно найти всю полную цепочку вывода S*.
Для построения вывода по алгоритму Кока—Янгера—Касами грамматика G(VT,VN,P,S) должна быть в нормальной форме Хомского. Поскольку, как было показано выше, любую произвольную КС-грамматику можно преобразовать в нормальную форму Хомского, это не накладывает дополнительных ограничений на применимость данного алгоритма.
Алгоритм Кока—Янгера—Касами фактически состоит из трех вложенных циклов. Поэтому ясно, что время выполнения алгоритма имеет кубическую зависимость от длины входной цепочки символов. Таблица Tn*n, используемая для хранения промежуточных данных в процессе работы алгоритма, является таблицей множеств. Очевидно, что требуемый для ее хранения объем памяти имеет квадратичную зависимость от длины входной цепочки символов.
Сам алгоритм Кока—Янгера—Касами можно описать следующим образом:
Шаг1.
Цикл для j от 1 до n
Т[1,j] := {А | Аaj Р} - в T[1,j] включаются все нетерминальные символы для которых в грамматике G существует правило Aaj
Конец цикла для j
Шаг 2.
Цикл для i от 2 до n
Цикл для j от 1 до n-i+1
T[1,j] = .
Цикл для k от 1 до i-1
T[1,j] := Т[1,j] {А | АВС Р, BT[k.j], CT[i-k, j+k]}
Конец цикла для k
Конец цикла для j
Конец цикла для i
Результатом работы алгоритма будет искомая таблица Tn*n. Для проверки существования вывода исходной цепочки в заданной грамматике остается только проверить условие ST[1,n].
Если вывод существует, то необходимо получить цепочку вывода. Для этого существует специальная рекурсивная процедура R. Она выдает последовательность номеров правил, которые нужно применить, чтобы получить цепочку вывода. Ее можно описать следующим образом: R(i,j,A), где AVN.
1. Если j=1 и существует правило Ааi, то выдать номер этого правила.
2. Иначе (если j > 1) возьмем k как наименьшее из чисел, для которых АВХ Р, BT[k,j], CT[i-k,j+k] (таких правил может быть несколько, для определенности берем наименьшее k). Пусть правило АВС имеет номер m. Тогда нужно выдать этот номер m, потом вызвать сначала R(i,k,B), а затем — R(i-k,j+k,C).
Для получения всей последовательности номеров правил нужно вызвать R(1,n,S).
Рекурсивная процедура R не требует дополнительной памяти для своего выполнения, кроме стека, необходимого для организации рекурсии. Время ее выполнения имеет квадратичную зависимость от длины входной цепочки.
На основании последовательности номеров правил, полученной с помощью алгоритма Кока—Янгера—Касами и рекурсивной процедуры R, можно построить левосторонний вывод для заданной грамматики G(VT,VN,P,S) и цепочки входных символов . Таким образом, с помощью данного алгоритма решается задача разбора.