- •Упрощенная модель компилятора. Проходы компилятора.
- •3. Проходы компиляторов
- •Задача идентификации. Транслитерация.
- •Методы лексического анализа.
- •Использование автомата для решения задачи идентификации слов (различные классы лексем).
- •Контекстно-свободные грамматики. Основные определения.
- •Задание кс грамматики. Способы задания грамматик: синтаксические диаграммы, форма Бекуса-Наура.
- •Выводы. Деревья синтаксического разбора.
- •Праволинейная грамматика.
- •Лишние нетерминалы.
- •Атрибутные грамматики. Наследуемые и синтезируемые атрибуты.
- •1 Синтезируемые атрибуты
- •2 Наследуемые атрибуты
- •Использование автоматов с магазинной памятью для нисходящего разбора.
- •Общие правила построения нисходящего распознающего автомата.
- •Распознающий автомат для s - грамматик.
- •Ll(1) - грамматики. Множество выбора.
- •Метод рекурсивного спуска.
- •Обработка ошибок при нисходящем разборе.Обнаружение и нейтрализация ошибок.
- •Восходящие методы синтаксического разбора. Метод перенос-свертка.
- •Задачи семантического анализа. Семантические соглашения.
Выводы. Деревья синтаксического разбора.
Синтаксический вывод - последовательность действий, которая позволяет определить является ли входная цепочка корректной для грамматики со стартового нетерминала.
Пример 1.
Грамматика:
<S> a<A><B>c
<S> ε
<A> c<S><A>
<A> <A>b
<B> b<B>
<B> a
Цепочка: acabac
Вывод:
<S>
a<A><B>c
ac<S><A><B>c
ac<A><B>c
Цепочка не является корректной, т.к. ее нельзя вывести из данной грамматики
Пример 2.
Грамматика:
<S> a<A><B>c
<S> ε
<A> c<S><B>
<A> <A>b
<B> b<B>
<B> a
Цепочка: acabac
Вывод:
<S>
a<A><B>c
ac<S><B><B>c
ac<B><B>c
aca<B>c
acab<B>c acabac
Цепочка является корректной в данной грамматике.
Дерево – граф, у которого нет циклов и петель.
Дерево синтаксического разбора:
<S>
1
a<A><B>c
3 5
c<S><B> b<B>
2 6 6
ε a a
Выписываем листья в порядке слева сверху вниз: acabac
Можно получить и другое дерево:
<S>
a<A><B>c
<A>b a
c<S><B>
ε a
При его обходе получаем все ту же цепочку: acabac.
оба
дерева дают корректные цепочки, а это
плохо, т.к. грамматика неоднозначна.
Если, используя одну и ту же грамматику, корректная цепочка может быть распознана двумя различными способами (два дерева), то такая грамматика называется неоднозначной. Такая грамматика не может быть использована для построения синтаксиса языка программирования.
Праволинейная грамматика.
Праволинейная – если правая часть каждого правила содержит не более одного нетерминального символа, и этот является самым правым символом правила.
Грамматика называется праволинейной, если она содержит только правила вида А→а, А→аВ.
Преобразование в праволинейную грамматику:
Пример 1 |
Пример 2 |
|
|
Задана грамматика:
<S> a<A>
<S> bc
<S> <A>
<A> abb<S>
<A> c<A>
<A> ε
Задача: построить автомат.
2,3,4 правила нуждаются в преобразовании.
2.
.
Обозначение «ε»
тут несущественно. Можно записать любой
символ.
4.
3.
- здесь просто переписываем все случаи
чему равно <A>
В результате получаем следующую грамматику:
<S> a<B>
<S> b<cε>
<cε> c<ε>
<ε> ε
<S> a<bbS>
<bbS> b<bS>
<bS> b<S>
<S> c<A>
<S> ε
<A> a<bbS>
<A> c<A>
<A> ε
Что можно записать следующей таблицей:
|
a |
b |
c |
|
<S> |
<A>,<bbS> - недетерминированность |
<cε> |
<A> |
допустимо |
<cε> |
- |
- |
<ε> |
- |
<ε> |
- |
- |
- |
допустимо |
<bbS> |
- |
<bs> |
- |
- |
<A> |
<bbS> |
- |
<A> |
допустимо |
<bs> |
- |
<S> |
- |
- |
Лишние нетерминалы.
Пример 1.
<S> a<S>a
<S> b<A>d
<S> c
<A> c<B>d
<A> a<A>d
<B> d<A>f
Проблема заключается в зацикливании между <A> и <B>.
Бесплодные (мертвые) нетерминалы – нетерминалы, которые не порождают ни одной терминальной цепочки.
Свойство 1. Если все символы правой части правила продуктивны, то продуктивны и символы в левой части.
<S> - продуктивный («плодовитый») символ
<A>,<B> - не продуктивные символы
Алгоритм проверки на продуктивность:
Составляем список нетерминалов, для которых найдется хотя бы одно правило, правая часть которого не содержит нетерминальных символов
Если найдено такое правило, то в список продуктивных терминалов заносится нетерминал, который стоит в левой части
Проверяются те правила, у которых в правой части стоят терминальные символы и нетерминальные символы из списка продуктивных. Если найдено такое правило, то нетерминал, стоящий в левой части,
заносится в список продуктивностей.
Повторяем эту операцию до тех пор, пока не будут проверены все правила грамматики. Если после проверки правил остались какие-то нетерминалы, которые не занесены в список продуктивных являются бесплодными (мертвыми).
Пример 2.
<S> a<S>b
<S> c
<A> b<S>
<A> a
<A> является недостижимым терминалом. Нетерминал, который не появится ни в одной цепочке, которая выводится со стартового терминала называется недостижимым.
Свойство 2. Если нетерминал в левой части правила является достижимым, то достижимы все символы в правой части.
Алгоритм проверки на достижимость:
Образовать список достижимых терминалов, внеся в него стартовый терминал
Если найдено правило, левая часть которого уже имеется в списке, то включить в список нетерминалы, имеющиеся в правой части
Если на шаге 2 список не пополняется новыми нетерминалами, то получен список всех достижимых нетерминалов. Нетерминалы, не попавшие в него считаются недостижимыми
Транслирующие грамматики. Перевод в польскую запись c использованием транслирующих грамматик.
Кс грамматика с символами действия - транслирующая
Лукасевич в 30-е гг. XX века предложил польскую запись (постфиксная и инфиксная форма записи).
Постфиксная запись: (a+b)*c ab+c*; -a+b a-b+
Грамматика, позволяющая формировать выражения в польской записи:
<операнд> <операнд><операнд>+
<операнд> <операнд><операнд>*
<операнд> I
Грамматика перевода (арифметических выражений):
<E> <E>+<T>{+}
<E> <T>
<T> <T>*<P>{*}
<T> <P>
<P> (<E>)
<P> a{a}
<P> b{b}
<P> c{c}
Символы, находящиеся в фигурных скобках { } называются символами действия. Они описывают процедуры, которые должны выполняться в этом месте.
Нетерминальными символами здесь являются все символы, стоящие в < >. А терминальными: a,b,c,+,*.
Сокращения: E – expression, T – term, P – prefix.
Словарь: {+,*,(,),a,b,c}
Пример: ((a+b*c)+a)
<E>
<T>
<P>
(<E>)
<E>+<T> {+}
<T> <P>
<P> a {a}
(<E>)
<E>+<T> {+}
<T> <T>*<P> {*}
<P> <P> с {c}
a {a} b{b}
При обходе символов действия получаем: {a}{b}{c}{*}{+}{a}{+}
a
bc*
+ a+
Вывод: перед нами транслирующая грамматика. Ее отличительная сторона: кроме терминальных и нетерминальных символов имеются символы действия. Проделанная операция называется переводом. С помощью грамматики мы можем произвести перевод.
