Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Все_пособие_редактир.doc
Скачиваний:
175
Добавлен:
31.10.2018
Размер:
2.51 Mб
Скачать

6. Нисходящий анализ

Нисходящий разбор можно рассматривать, как попытку найти левое порождение вход­ной строки. Так же его можно рассматривать и как попытку построить дерево разбо­ра для входной строки, начиная с корня и создавая вершины в прямом порядке.

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

Рассмот­рим нисходящий анализ в общем виде, а именно — анализ методом рекурсивного спуска, который может использовать откаты, т.е. производить повторное сканирование входного потока. Однако такие синтаксические анализаторы с откатом встречаются редко. При анализе языков программирования технология отката не очень эффективна, и предпочтительными являются табличные методы.

Рассмотрим пример, в котором откат необходим.

Пример 15

Рассмотрим грамматику

S → cAd

Aab|a

и входную строку w = cad.

При нисходящем построении дерева разбора для этой строки вначале создаем дерево, состоящее из одного узла, помеченного как S. Указатель входа указывает на с, первый символ строки w. Теперь воспользуемся первой продукцией для S, чтобы получить дерево, показанное на рис. 27а.

Рис. 27. Шаги нисходящего разбора

Крайний слева лист, с, соответствует первому символу строки w, так что переместим указатель входа к а, второму символу строки w, и рассмотрим следующий лист дерева, помеченный А. Теперь можно воспользоваться для А первой альтернативой и получить дерево, изображенное на рис. 27б. Здесь обнаружено соответствие считанного символа листу дерева, и осуществляется переход к следующему символу — d. Однако d не соответствуют листу дерева b, значит, надо вернуться к А с тем, чтобы выбрать новую альтернативу для работы.

Возвращаясь к А, необходимо вернуть указатель входа в позицию 2, в которой он был когда впервые выбирали продукцию для разложения А. Это означает, что процедура для А должна хранить указатель входа в локальной переменной. При рассмотрении второй альтернативы для А получаем дерево, показанное на рис. 21в. Лист а соответствует второму символу w, а лист d - третьему. Поскольку в этот момент построено дерево разбора для w, прекращаем работу и сообщаем об успешном завершении разбора.

Леворекурсивная грамматика может вызвать зацикливание синтаксического анализатора, работающего методом рекурсивного спуска, даже с откатами (при разборе А может потребоваться вновь проанализировать А, находясь в той же входной позиции, что автоматически приводит к бесконечной рекурсии).

6.2 Предиктивные анализаторы

Во многих случаях аккуратная разработка грамматики, устранение из нее левой рекурсии и ее левая факторизация позволяют получить грамматику, которая может быть проанализирована синтаксическим анализатором, работающим методом рекурсивно спуска и не требующим отката. Для построения предиктивного синтаксического анализатора необходимо знать, какая из альтернатив A α12|…|αn данного анализируемого нетерми­нала A, порождает строку, начинающуюся с полученного входного символа а. То есть правильная альтернатива должна точно определяться по первому, порождаемому ею символу. Обычно в языках программирования управляющие конструкции отвечают этому правилу. Например, если есть продукции

stmt → if expr then stmt else stmt |while expr do stmt | begin stmt_list end

то ключевые слова if, while и begin однозначно определяют возможную альтернативу для рассматриваемой инструкции stmt.