Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

nC1DMY1V3A

.pdf
Скачиваний:
4
Добавлен:
15.04.2023
Размер:
1.71 Mб
Скачать

10.Сформулируйте равила построения нисходящего МП-распознавателя для языков, порождаемых Q-грамматикой.

11.Как строятся множества ПЕРВ для произвольной цепочки терминалов и нетерминалов?

12.Дайте определение множества выбора правил грамматики.

13.Дайте формальное определение LL(1)-грамматики.

14.Опишите алгоритм нисходящего разбора для LL(1)-грамматик.

15.Сформулируйте правила заполнения управляющей таблицы нисходящего МП-распознавателя для языков, порождаемых LL(1)-граммати- кой.

16.Опишите алгоритм метода рекурсивного спуска.

17.При какой реализации компиляторов возможно использование метода рекурсивного спуска?

70

Тема 6. Формальные методы описания перевода

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

Введем следующие действия МП-автомата:

операция ввода – ЧИТАТЬ – сдвиг МП-автомата на один символ; операция вывода – ПЕЧАТАТЬ – процедура, которую вызывает ав-

томат.

В качестве примера рассмотрим преобразование выражений из инфиксной формы в постфиксную.

Пусть на вход подается цепочка вида: a b c В результате последовательности действий:

ЧИТАТЬ(a) ПЕЧАТАТЬ(a) ЧИТАТЬ( ) ЧИТАТЬ(b) ПЕЧАТАТЬ(b) ЧИТАТЬ( ) ЧИТАТЬ(c) ПЕЧАТАТЬ(c) ПЕЧАТАТЬ( ) ПЕЧАТАТЬ( ) получаем на выходе цепочку вида: abc*+

Представленную последовательность действий можно обобщить и записать, не используя слова ЧИТАТЬ и ПЕЧАТАТЬ:

a {a} + b {b} c {c} { } { }

Вэтом случае операции ввода представляются входными символами,

аоперации вывода – символами, заключенными в фигурные скобки.

Такая последовательность будет называться последовательностью актов.

Пару фигурных скобок и заключенный в них символ рассматривают как единый символ и называют символом действия.

Приведенная выше последовательность актов содержит 5 символов действия. В этом примере символы действия рассматриваются как имена процедур, которые печатают входные символы.

Данная последовательность актов говорит о том, как можно обработать одно конкретное инфиксное выражение. Для того, чтобы показать как обработать все инфиксные выражения, нужно описать множество или язык последовательностей актов.

Транслирующая грамматика

Ставится задача описания языков последовательностей актов с помощью КС-грамматик.

Разработаем такое описание для рассмотренного выше примера. Исходным пунктом при разработке КС-описания языка последова-

тельности актов служит грамматика для входного языка. Для инфиксных арифметических выражений она такова:

71

1.<E> <E> <T>

2.<E> <T>

3.<T> <T> <P>

4.<T> <P>

5.<P> (<E>)

6.<P> a

7.<P> b

8.<P> c

Для удобства изложения грамматика содержит три конкретных имени переменных a, b, c. Чтобы построить грамматику для последовательности актов, запишем действия, соответствующие каждой правой части правил грамматики:

1. <E> <E> <T>{ }

Интерпретация этой записи: «Обработка <E> состоит из обработки <E>, чтения , обработки <T> и печати »

2.<E> <T>

3.<T> <T> <P>{ }

4.<T> <P>

5.<P> (<E>)

6.<P> a{a}

7.<P> b{b}

8.<P> c{c}

Эта новая грамматика является примером транслирующей грамма-

тики или грамматики перевода.

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

Например, рассмотрим инфиксное выражение (a b) c.

Левый вывод этой цепочки получается применением правил 2, 3, 4,

5, 1, 2, 4, 6, 4, 7, 8:

 

 

<E>

<T>

<T> <P> <P> <P>

(<E>) <P>

(<E> + <T>)

<P> * (a+b) c

 

Эта

же последовательность правил

транслирующей грамматики,

применяемая к левым нетерминалам, дает вывод последовательности актов для этой входной последовательности:

<E> <T>

<T> <P>{ }

<P> <P>{ }

(<E>) <P>{ }

(<E>+<T>{

}) <P>{ }

* (a{a}+b{b}{

}) c{c}{ }

Определение 6.1. Транслирующей грамматикой или грамматикой перевода называется КС-грамматика, множество терминальных символов которой разбито на множество входных символов и символов действия.

72

Определение 6.2. Цепочка языка, определяемого транслирующей грамматикой, называется последовательностью актов.

Еще один пример транслирующей грамматики: входные символы = {a, b, c}

символы действия = {{x}, {y},{z}} нетерминальные символы = {<A>, <B>} начальный нетерминал = <A>

набор правил:

1.<A> a<A>{x}<B>

2.<A> {z}

3.<B> <B>c

4.<B> b{y}

Термин «грамматика, транслирующая в цепочки» или «грамматика цепочечного перевода» указывает на то, что данная транслирующая грамматика предназначена для описания перевода входных цепочек в выходные.

Рассмотрим проблему выполнения синтаксически управляемого цепочечного перевода, определяемого транслирующими грамматиками.

В частности, рассмотрим те транслирующие грамматики, входные грамматики которых являются S-грамматиками.

Метод преобразования стандартного МП-автомата заключается в следующем: берется каждый переход, в котором исполняется правило данной входной грамматики, и изменяется так, чтобы в нем учитывалось соответствующее правило транслирующей грамматики.

Проиллюстрируем этот подход на конкретном примере: Пусть в некоторой транслирующей грамматике есть правило:

A { }a{ }<B>{x}c{y}<D>{z}

Оно соответствует следующему правилу входные грамматики

A a<B>c<D>

Правило перехода в управляющей МП-грамматике выглядит так ЗАМЕНИТЬ ( D c B ), СДВИГ

Необходимо так изменить этот переход, чтобы в соответствующие моменты времени происходила выдача символов , , x, y, z.

При этом используется две различные стратегиидля символов ,

и для x, y, z.

Выдачу символов и необходимо задать, добавив выходную операцию ВЫДАТЬ{ , } в операции данного перехода, так как они примыкают к терминалу а, который обрабатывается в момент чтения.

Выдачу символов x, y, z, нельзя осуществить как часть данного перехода, поскольку транслирующая грамматика показывает, что выходные символы и , отделимы в выходной последовательности переводом цепочки, выводимой из нетерминала B .

73

Для того, чтобы обеспечить выдачу этих символов необходимо в надлежащие моменты времени, операцию ЗАМЕНИТЬ модифицировать так, чтобы поместить в магазин новые символыx, y, z.

Таким образом переход измененного МП-автомата можно записать

так:

ВЫДАТЬ (), ЗАМЕНИТЬ ({z}< D>{y}c{x}<B>), СДВИГ

Когда наверху магазина оказывается символ действия, автомат выдает соответствующий выходной символ, удаляет символ действия из магазина и удерживает входной символ.

Правила построения нисходящего распознавателя, описанные в

теме 5, изменяются в описании перехода 4.1

 

если правило имеет вид

A

b

, где

 

A

нетерминал, b

терминал,

,

цепочки символов действий

(возможно пустые),

цепочка, состоящая из терминалов, нетерминалов

и символов действий, тогда переход, стоящий в управляющей таблице на пересечении терминала b и нетерминала <A>, выглядит так:

ВЫДАТЬ ( ) ЗАМЕНИТЬ ( r), СДВИГ

 

это содержимое фигурных скобок символа действий.

Если

, пустые цепочки, то команда ВЫДАТЬ опускается.

Если

пуста, то ЗАМЕНИТЬ превращается в ВЫТОЛКНУТЬ.

Кроме того, правила построения управляющей таблицы дополняются еще одним: если символ действия {x} оказался магазинным символом, то элемент таблицы соответствующей строке {x} будет выглядеть так:

ВЫДАТЬ (x), ВЫТОЛКНУТЬ, ДЕРЖАТЬ.

Синтаксически управляемый перевод

С математической точки зрения, перевод рассматривается как множество пар, где первый элемент принадлежит множеству объектов, которые надо перевести, а второй элемент пары – множеству объектов, которые являются результатами перевода.

Внашем случае первый элемент пары – это цепочка входного языка,

авторой элемент – последовательность, представляющая результат перевода входной цепочка.

Когда эти пары получаются с помощью некоторой грамматики, перевод называют синтаксически управляемым переводом. Понятие последовательности актов можно использовать как основу одного класса син-

таксически управляемых переводов.

Пусть дана последовательность актов, состоящая из входных символов и символов действия. Будем называть входной подпоследовательностью последовательность входных символов, полученную из последовательности актов путем вычеркивания всех символов действия, и подпосле-

74

довательностью действий – последовательность, полученную из последовательности актов путем вычеркивания всех входных символов.

Говорят, что входная подпоследовательность образует пару с под-

последовательностью действий.

 

Для последовательности актов

a{a}+ b{b} c{c}{ }{ }:

входная подпоследовательность

a + b c

подпоследовательность действий

{a}{b}{c}{ }{ }

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

Пусть дана транслирующая грамматика:

1. <E>

<E> + <T> {+}

2. <E>

<T>

3. <T>

<T> * <P> {*}

4. <T>

<P>

5. <P>

(<E>)

6. <P>

a {a}

7. <P>

b {b}

8. <P>

c {c}

Грамматика, полученная путем вычеркивания из правил всех символов действия, называется входной грамматикой для этой транслирующей грамматики:

1. <E>

<E> + <T>

2. <E>

<T>

3. <T>

<T> * <P>

4. <T>

<P>

5. <P>

(<E>)

6. <P>

a

7. <P>

b

8. <P>

c

Язык, определяемый входной грамматикой, называется входным языком.

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

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

Для данной транслирующей грамматики выходную грамматику, или грамматику действий, можно получить вычеркиванием входных символов:

1. <E>

<E> <T> {+}

2. <E>

<T>

3. <T>

<T> <P> {*}

 

75

4. <T>

<P>

5. <P>

<E>

6. <P>

{a}

7. <P>

{b}

8. <P>

{c}

Таким образом, транслирующую грамматику можно рассматривать как переводящую с одного КС-языка, входного языка, на другой КС-язык, выходной язык или язык действия.

Понятие атрибута.

Синтезированные и наследуемые атрибуты

Ранее рассматривались переводы цепочек символов в цепочки символов. Использованные символы принадлежали некоторым конечным множествам, и в понятие символа не включалось представление о том, что он должен состоять из двух частей: значения и класса.

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

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

Такое расширение называется атрибутной грамматикой.

Прежде, чем ввести полное описание атрибутной грамматики, продемонстрируем на примере понятие «синтезируемого атрибута».

Предположим, что существует лексический блок, задающий входное множество

{( , ), , , c},

где с – лексема, представляющая константу; ее значением является значение константы, построенное лексическим блоком.

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

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

1.<S> <E> {ответ}

2.<E> <E> <T>

3.<E> <T>

4.<T> <T> <P>

5.<T> <P>

6.<P> (<E>)

7.<P> c

76

Значение выходного символа ОТВЕТ должно быть числом. Требуемое отношение между значением входных лексем и значением выходной лексемы ОТВЕТ можно выразить словами «значение лексемы ОТВЕТ – это числовое значение входного выражения».

Необходимо найти математический способ выражения отношения, описанного этой фразой.

Рассмотрим конкретную входную цепочку (c3 c8) (c2 c4), где значения входных лексем, выданных лексическим блоком, указаны нижними индексами. Этой входной цепочке соответствует выходная цепочка ОТВЕТ66.

Дерево вывода, соответствующее этой входной цепочке – рис. 6.1.

Рис. 6.1. Дерево вывода цепочки (c3 c8 ) (c2 c4 )

Самый естественный способ определения значения данного входного выражения состоит в определении значения каждой его части.

Пометим на дереве каждый нетерминал значением соответствующего подвыражения, а выходной символ – требуемым выходным значением

(рис. 6.2).

Рис. 6.2. Разметка дерева вывода цепочки (c3 c8 ) (c2 c4 )

77

Для математической строгости дополним имеющиеся правила правилами вычисления значений левых частей

1.

<S>

<E>q {ответr}

 

r

q

 

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

 

 

 

 

значение выражения в правой части, то есть (q r).

2. <E>p

<E>q

<T>r

 

p

q

r,

 

3. <E>p

<T>q

 

 

p

q

 

 

4. <T>p

<T>q

<P>r

 

p

q

r

 

5. <T>p

<P>q

 

 

p

q

 

 

6. <P>p

(<E>q)

 

p

q

 

 

7. <P>p

cq

 

 

pq

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

Приведенные выше продукции, вместе с соответствующими правилами вычисления значений, являются примерами «атрибутных правил» или «атрибутных продукций», и взятые вместе с начальным нетерминалом

<S>, образуют «атрибутную грамматику».

Вэтой терминологии значения вышеприведенных символов называ-

ются «атрибутами».

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

Рассмотрим пример, показывающий, каким образом можно определить атрибутную информацию так, чтобы она распространялась вниз по дереву вывода.

Рассмотрим грамматику с начальным символом <описание>:

1.

<описание> ТИП V<список переменных>

2.

< список переменных >

, V<список переменных>

3.

< список переменных >

ɛ

Эта грамматика порождает описания, подобные тем, что встречаются во многих языках программирования.

Предположим, что существует лексический блок, задающий три лексемы: {V ТИП ,} , где

78

лексема V обозначает переменную, и ее значение является указателем на соответствующий этой переменной элемент таблицы имен;

ТИП – лексема со значением, определяющим, какой из типоввещественный, целый или логический, – должен быть поставлен в соответствие переменным из данного списка.

При обработке описания каждой переменной синтаксический блок вызывает процедуру УСТАНОВИТЬ-ТИП, которая помещает один из типоввещественный, целый или логический, – в надлежащее поле элемента таблицы имен, соответствующее данной переменной.

Вызов УСТАНОВИТЬ-ТИП лучше всего осуществлять сразу после того, как переменная поступила на вход синтаксического блока.

Такая синхронизация описывается следующей транслирующей грамматикой:

1.

<описание> ТИП V {УСТАНОВИТЬ ТИП} <список перемен-

ных>

 

2.

<список переменных> , V {УСТАНОВИТЬ ТИП} <список пере-

менных>

3.

< список переменных > ɛ

Процедура УСТАНОВИТЬ ТИП может иметь два аргумента указатель на элемент таблицы имен, соответствующий переменной, и тип переменной.

Тогда вызов процедуру УСТАНОВИТЬ ТИП можно записать так УСТАНОВИТЬ ТИП(указатель, тип).

Необходимо ввести в вышеприведенную грамматику атрибуты и правила их вычисления.

Символ действия {УСТАНОВИТЬ ТИП} с его атрибутами иллюстрирует разницу между атрибутом и значением. У этого символа имеется два атрибута – указатель и тип, и одно значение – пара (указатель, тип).

Таким образом, понятие атрибута – это уточнение понятия значения. Итак, правила с атрибутами

1.

<описание>

 

ТИПtVp {УСТАНОВИТЬ ТИП}p1 t1<список перемен-

 

ных>t2

 

 

 

 

(t1, t2)

t,

p1 p

 

2.

<список переменных>t

, Vp {УСТАНОВИТЬ ТИП}p1 t1 <список

 

переменных>t2,

 

 

(t1, t2)

t,

p1 p

 

3.

<список переменных>t

ɛ

Запись (t1, t2)

 

t означает, что значение t присваивается одновре-

менно t1и t2.

На рисунке 6.3 показано атрибутное дерево вывода последовательности ТИПвещV1, V2, V3 определенное этой грамматикой.

79

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