
- •Часть 2. Дискретная математика. Структуры данных. Алгоритмы. Информатика.
- •4.1. Ограниченно-детерминированные функции
- •Ограниченно-детерминированные функции
- •Открытое хеширование
- •Закрытое хеширование
- •Метод остатков от деления
- •Метод функции середины квадрата
- •Метод свертки
- •Семафорные примитивы Дейкстры
- •4.6 Семафорные примитивы Дейкстры.
- •Концепция
- •Задача “Поставщик - Потребитель”.
- •Мониторы Хоара
- •[Править]Тип 0 — неограниченные
- •[Править]Тип 1 — контекстно-зависимые
- •[Править]Тип 2 — контекстно-свободные
- •[Править]Тип 3 — регулярные
- •Синтаксический анализ
- •Условия использования метода рекурсивного спуска
- •Устранение левой рекурсии
- •[Править]Устранение непосредственной левой рекурсии
- •[Править]Пример
- •[Править]Алгоритм устранения произвольной левой рекурсии
- •[Править]Асимптотика
- •[Править]Пример
- •[Править]Варианты реализации [править]Предсказывающий парсер
- •[Править]Парсер с возвратом
- •Виртуальные и динамические методы
- •Динамические методы
- •Символьные массивы (строки)
- •Создание функции
- •Формальные и фактические параметры
- •Очередность вызова и рекурсия
- •Способы передачи параметров в функцию
- •Перегрузка функций
- •Абстракция данных
- •Ключевые черты ооп
- •Наследование
- •Private-наследование
- •Protected-наследование
- •Public-наследование
- •Статические члены класса
- •Указатель this
- •Перегрузка операторов
- •Примеры некоторых классов Класс комплексных чисел
- •Аналитическая модель поверхности
- •Векторная полигональная модель
- •Воксельная модель
- •Равномерная сетка
Условия использования метода рекурсивного спуска
Метод рекурсивного спуска без возвратов можно использовать только для грамматик, правила которых удовлетворяют следующему условию: первого символа каждого правила должно быть достаточно для того, чтобы определить, какое правило применимо в данном случае. Более точно это условие можно формализовать путем определения множества FIRST.
Определение.Для КС-грамматики G и цепочки w, состоящей из терминальных и нетерминальных символов, определим множество FIRST k (w) следующим образом:
FIRST k (w) = {x | w =>* xv, |x| = k или w =>* x, |x| < k}, где k - натуральное число.
Иными словами, множество FIRST k (w) состоит из всех терминальных префиксов длины k терминальных цепочек, выводимых из w.
Пример.Рассмотрим грамматику, порождающую подмножество типов языка Pascal.
Для этой грамматики мы имеем:
FIRST1 (simple) = {integer, char, num}
FIRST1 (^id) = {^}
FIRST1 (array [simple] of type) = { array }
Понятно, что если цепочка w состоит только из терминалов, то FIRST k (w) - это первые k символов цепочки w , если |w| >=, или это сама цепочкаw, если |w| < k <
Устранение левой рекурсии
Определение: |
Говорят,
что контекстно-свободная
(КС) грамматика |
Определение: |
Говорят, что
КС-грамматика
содержит левую
рекурсию (left recursion),
если в ней существует вывод вида |
Методы нисходящего разбора (top-down parsers) не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.
[Править]Устранение непосредственной левой рекурсии
Опишем
процедуру, устраняющую все правила
вида
,
для фиксированного нетерминала
.
Запишем все правила вывода из в виде:
, где
— непустая последовательность терминалов и нетерминалов (
);
— непустая последовательность терминалов и нетерминалов, не начинающаяся с .
Заменим правила вывода из на
.
Создадим новый нетерминал
.
Изначально
нетерминал
порождает
сроки вида
.
В новой грамматике нетерминал
порождает
,
а
порождает
строки вида
.
Из этого очевидно, что изначальная
грамматика эквивалентна новой.
[Править]Пример
Есть
непосредственная левая рекурсия
.
Добавим нетерминал
и
добавим правила
,
.
Новая грамматика:
В
новой грамматике нет непосредственной
левой рекурсии, но нетерминал
леворекурсивен,
так как есть
[Править]Алгоритм устранения произвольной левой рекурсии
Воспользуемся алгоритмом
удаления
-правил.
Получим грамматику без
-правил
для языка
.
Упорядочим
нетерминалы и будим добиваться того,
чтобы не было правил вида
,
где
.
Если данное условие выполняется для
всех
,
то в грамматике нет
,
а значит не будет левой рекурсии.
Пусть
—
упорядоченное множество всех нетерминалов.
for все нетерминалы
for
все нетерминалы
,
такие, что
и
рассмотреть
все правила вывода из
:
.
заменить
каждое правило
на
.
устранить непосредственную левую рекурсию для .
Если
присутствовал
в языке исходной грамматики, добавим
новый начальный символ
и
правила
.
После
итерации
внешнего цикла в любой продукции внешнего
цикла в любой продукции вида
,
должно быть
.
В результате при следующей итерации
внутреннего цикла растет нижний
предел
всех
продукций вида
до
тех пор, пока не будет достигнуто
.
После
итерации
внешнего цикла в грамматике будут только
правила вида
,
где
.
Можно заметить, что неравенство становится
строгим только после применения алгоритма
устранения непосредственной левой
рекурсии. При этом добавляются новые
нетерминалы. Пусть
новый
нетерминал. Можно заметить, что нет
правила вида
,
где
самый
левый нетерминал, а значит новые
нетерминалы можно не рассматривать во
внешнем цикле.
На
итерации
внешнего цикла все правила
вида
где
заменяются
на
где
.
Очевидно, что одна итерация алгоритма
не меняет язык, а значит язык получившийся
в итоге грамматики совпадает с исходным.