- •Глава 12 Классы кс-языков
- •Алгоритм разбора по методу рекурсивного спуска
- •Пример реализации метода рекурсивного спуска
- •Расширенное применение распознавателей на основе метода рекурсивного спуска
- •Определение ll(k)-грамматики
- •Принципы построения распознавателей для ll(к)-грамматик
- •Алгоритм разбора для ll(1)-грамматик
- •Алгоритм построения множества first(1,a)
- •Алгоритм построения множества follow(1,a)
- •Пример построения распознавателя для ll(1)-грамматики
- •Принципы построения распознавателей для lr(k)-грамматик
- •Распознаватель для lr(0)-грамматики
- •Распознаватель для lr(1)-грамматики
- •Грамматики предшествования (основные принципы)
- •Грамматики простого предшествования
- •Алгоритм «сдвиг-свертка» для грамматики простого предшествования
- •Пример распознавателя для грамматики простого предшествования
- •Грамматики операторного предшествования
- •2. Различные порождающие правила имеют разные правые части, λ-правила отсутствуют.
- •Алгоритм «сдвиг-свертка» для грамматики операторного предшествования
- •Отношения между классами кс-грамматик
- •Отношения между классами кс-языков
Пример реализации метода рекурсивного спуска
Необходимо построить распознаватель, работающий по методу рекурсивного спуска.
Видно, что грамматика удовлетворяет условиям, необходимым для построения такого распознавателя.
Напишем процедуры на языке программирования С, которые будут обеспечивать разбор входных цепочек языка, заданного данной грамматикой. Согласно алгоритму, необходимо построить процедуру разбора для каждого нетерминального символа грамматики, поэтому дадим процедурам соответствующие наименования. Входные данные для процедур разбора будут следующие:
--- цепочка входных символов;
---положение указателя (считывающей головки МП-автомата) во входной цепочке;
--- массив для записи номеров примененных правил; G порядковый номер очередного правила в массиве.
Результатом работы каждой процедуры может быть число, отличное от нуля («истина»), или 0 («ложь»). В первом случае входная цепочка символов принимается распознавателем, во втором случае — не принимается. Для удобства реализации в том случае, если цепочка принимается распознавателем, будем возвращать текущее положение указателя в цепочке. Кроме того, потребуется еще одна дополнительная процедура для ведения записей в массиве последовательности правил (назовем ее WriteRules).
Теперь для распознавания входной цепочки необходимо иметь целочисленный массив Rules достаточного объема для хранения номеров правил. Тогда работа распознавателя заключается в вызове процедуры proc_S(Str,0,Rules,&N), где Str — это входная цепочка символов, N — переменная для запоминания количества примененных правил (первоначально N = 0). Затем требуется обработка полученного результата: если результат на 1 превышает длину цепочки — цепочка принята иначе — цепочка не принята. В первом случае в массиве Rules будем иметь последовательность номеров правил грамматики, необходимых для вывода цепочки, а в переменной N — количество этих правил. На основе этой цепочки можно легко построить дерево вывода.
Объем массива Rules заранее не известен, так как заранее не известно количестве шагов вывода. Чтобы избежать проблем с недостаточным объемом статической массива, приведенные выше процедуры распознавателя можно модифицировав так, чтобы они работали с динамическим распределением памяти (изменив процедуру WriteRules и тип параметра piRul в вызовах остальных процедур). На логику работы распознавателя это никак не повлияет. Следует помнить также, что метод рекурсивного спуска основан на рекурсивном вызове множества процедур, что при значительной длине входной цепочки символов может потребовать соответствующего объема стека вызовов для хранения адресов процедур, их параметров и локальных переменных (более подробно об этом можно посмотреть в данном пособии в разделе «Семантический анализ и подготовка к генерации кода», глава 14).
Из приведенного примера видно, что алгоритм рекурсивного спуска удобен и прост в реализации. Главным препятствием в его применении является то, что класс грамматик, допускающих разбор на основе этого алгоритма, сильно ограничен.
