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

Пример реализации метода рекурсивного спуска

Необходимо построить распознаватель, работающий по методу рекурсивного спуска.

Видно, что грамматика удовлетворяет условиям, необходимым для построения такого распознавателя.

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

--- цепочка входных символов;

---положение указателя (считывающей головки МП-автомата) во входной цепочке;

--- массив для записи номеров примененных правил; G порядковый номер очередного правила в массиве.

Результатом работы каждой процедуры может быть число, отличное от нуля («истина»), или 0 («ложь»). В первом случае входная цепочка символов принимается распознавателем, во втором случае — не принимается. Для удобства реализации в том случае, если цепочка принимается распознавателем, будем возвращать текущее положение указателя в цепочке. Кроме того, потребуется еще одна дополнительная процедура для ведения записей в массиве последовательности правил (назовем ее WriteRules).

Теперь для распознавания входной цепочки необходимо иметь целочисленный массив Rules достаточного объема для хранения номеров правил. Тогда работа распознавателя заключается в вызове процедуры proc_S(Str,0,Rules,&N), где Str — это входная цепочка символов, N — переменная для запоминания количества примененных правил (первоначально N = 0). Затем требуется обработка полученного результата: если результат на 1 превышает длину цепочки — цепочка принята иначе — цепочка не принята. В первом случае в массиве Rules будем иметь последовательность номеров правил грамматики, необходимых для вывода цепочки, а в переменной N — количество этих правил. На основе этой цепочки можно легко построить дерево вывода.

Объем массива Rules заранее не известен, так как заранее не известно количестве шагов вывода. Чтобы избежать проблем с недостаточным объемом статической массива, приведенные выше процедуры распознавателя можно модифицировав так, чтобы они работали с динамическим распределением памяти (изменив процедуру WriteRules и тип параметра piRul в вызовах остальных процедур). На логику работы распознавателя это никак не повлияет. Следует помнить также, что метод рекурсивного спуска основан на рекурсивном вызове множества процедур, что при значительной длине входной цепочки символов может потребовать соответствующего объема стека вызовов для хранения адресов процедур, их параметров и локальных переменных (более подробно об этом можно посмотреть в данном пособии в разделе «Семантический анализ и подготовка к генерации кода», глава 14).

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]