Языки программирования Лекция 6

advertisement
Синтаксический анализ
Исходная
программа
Токен
Лексический
анализатор
запрос
следующего
Синтаксический
анализатор
Таблица
символов
Дерево
разбора
Семантический
разбор и т.п.
Классы синтаксических
анализаторов
• Нисходящие анализаторы, которым
соответствуют LL-грамматики
• Восходящие анализаторы, которым
соответствуют LR-грамматики
• Переборные анализаторы –
экспоненциальная трудоемкость.
Синтаксический анализ КС-языков
Стратегия 1. «Cверху-вниз» – нисходящий анализ.
Основной принцип: Выводим из начального нетерминала все возможные
цепочки методом «поиска в глубину». Поиск останавливается, если
сгенерированная цепочка отличается от входной. Чтобы метод
работал, желательно, чтобы «поиск в глубину» раскрывал самый
левый из нераскрытых нетерминалов, иначе сложно проверять
совпадение входной цепочки с уже сгенерированной.
Недостаток метода: сложно выполнять атрибутные вычисления, т.к. при
откате при поиске необходимо нейтрализовать возможные побочные
эффекты атрибутивных вычислений.
Преимущество: для определённых видов грамматик удаётся реализовать
поиск без возвратов, а потом очень просто можно запрограммировать
весь синтаксический анализ методом «рекурсивного спуска».
Синтаксический анализ КС-языков
Стратегия 2. «Снизу-вверх» – восходящий анализ.
Основной принцип: Начиная с терминальной строки листьев дерева
пытаемся найти т.н. «связку» – правую часть некоторой продукции
грамматики, которую нужно заменить нетерминалом в левой части
продукции, чтобы получить новый узел в дереве разбора.
Формально: Связкой цепочки вывода называется самая левая цепочка β
(возможно пустая) в µ, такая, что существует вывод S  *A    
Недостаток метода: для реальной цепочки вывода достаточно сложно
найти связку, а если её и нашли, то в дальнейшем связок может и не
быть вообще, а потому придётся возвращаться и повторять поиск
иной связки.
Преимущество: для некоторых видов грамматики удаётся найти очень
простые правила поиска связок, позволяющие создать очень быстрые
алгоритмы синтаксического разбора.
Подклассы КС-грамматик, допускающие
эффективные методы синтаксического анализа
КС-грамматики
Грамматики
простого
предшествования
LL(1)-грамматики
s-грамматики
LR(0)-грамматики
LALR(k)-грамматики
SLR(k)-грамматики
... ...
Нисходящие методы
синтаксического анализа
Пусть у нас имеется некоторая грамматика и вывод
S  1   2   3   4 ...  abcdeabbaa dec
В восходящем анализе вначале находится некоторая «связка» и, по сути, определяется, какое правило было применено на некотором этапе вывода:
S  ...i  i 1...  abcdeabbaadec
В нисходящем анализе всегда восстанавливается самое первое правило,
которое применено при выводе:
S  1  ...  abcdeabbaadec
Пример. Дана грамматика: S  aBDe | bCBD, …
Пусть дана цепочка S  ...  abcdeabbaadec .
Очевидно, что самым первым правилом, которое было применено для
вывода цепочки abcdeabbaadec , было правило S  aBDe, т.к. иначе первым
символов выведенной цепочки был бы символ b.
Грамматики, которые допускают последовательное восстановление
всех этапов вывода  i ,  i 1 ,  i  2 ,... на основании не более чем очередных k
символов выведенной цепочки, называется LL(k)-грамматикой
Автоматные грамматики
Автоматными грамматиками являются такие грамматики, которые
имеют правилами вывода типа A  aB | a |  .
Пример автоматной грамматики.
S  aS | bA
A  aB | 
B  bA | a
Пример вывода в этой грамматике:
S  bA  baB  babA  babaB  bababA babab
S
A
B
A
B
A
b
a
b
a
b

LL-грамматика
• Анализ без возвратов
• Первая буква L означает просмотр входной
цепочки слева направо (leftto-right scan)
• Вторая буква L означает, что строится левый
вывод цепочки (leftmost derivation).
• k – количество очередных символов,
необходимых восстановления вывода
цепочки
Метод рекурсивного спуска
• Анализ методом рекурсивного спуска (recursive-descent
parsing) – способ синтаксического анализа, при котором
выполняется ряд рекурсивных процедур для обработки
входного потока
• Каждая процедура – связана с соответствующим
нетерминалом
• Вариант без возвратов можно использовать только для
грамматик с правилами, в которых первого символа
каждого правила должно быть достаточно для того,
чтобы определить, какое правило применять
Рекурсивный спуск с возвратами
Для обхода трудностей, связанных с совпадением
множеств FIRST, на практике зачастую используется
следующий прием:
– Перед началом разбора потенциально неоднозначного
фрагмента запоминается текущее состояние лексического
анализатора
– Затем запускается разбор первой из возможных конструкций
– В случае неудачного завершения разбора, мы восстанавливаем
состояние лексического анализатора и переходим к
следующему варианту разбора и т.д.
– Если все варианты завершаются неудачно, то мы сообщаем об
ошибке
LL(k)-грамматика
Определение. Грамматика G = (VT, VN, P, S)
называется LL(k)-грамматикой, если для
любых двух левых выводов
S =>* wAv => wuv =>* wx
S =>* wAv => wu1v =>* wy
для которых FIRSTk (x) = FIRSTk (y) верно, что
u=u1.
Леворекурсивные грамматики
• Грамматика называется леворекурсивной,
если среди ее нетерминалов имеется по
крайней мере один леворекурсивный
нетерминал.
• Нетерминал A называется леворекурсивным,
если существует вывод A =>* Aw.
• Леворекурсивные грамматики не обладают
свойством LL(k) ни для какого k.
Левая рекурсия
Определение. КС-грамматика называется леворекурсивной, если в ней существует вывод A  *A .
Леворекурсивные грамматики достаточно неудобны на практике для синтаксического анализа. В частности нисходящие методы синтаксического анализа, восстанавливающие дерево вывода от его корня, не могут быть применены для таких грамматик.
Рассмотрим пару продукций A  A |  .
Эти правила порождают цепочки вида . Эти же цепочки можно также породить и эквивалентными правилами: A  R ; R  R |  .
Соответственно дерево вывода будет другое в этой грамматике: праворекурсивное, а не леворекурсивное:
A
A
R
A
R
A
R
A

R








Пример. Рассмотрим фрагмент правил классической грамматики арифметических
выражений: E  E  T | T .
Эквивалентная грамматика: E  TE' ; E'  TE'|  .
Download