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

9.3 Синтезируемые атрибуты

Синтезируемые атрибуты часто используются на практике.

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

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

Пример 31

S-атрибутное определение в примере 30 описывает калькулятор, считывающий арифметическое выражение из цифр, скобок, операторов + и *, за которым следует символ новой строки n, и выводит значение выражения. Например, получив выражение 3*5+4, за которым следует символ новой строки, программа выводит значение 19. На рис. 50 показано аннотированное дерево разбора для входной строки 3*5+4n. Выход программы, печатаемый в корне дерева, представляет собой значение E.val в первом дочернем узле корня дерева.

Вычисление значений атрибутов производится следующим образом. Крайнему слева снизу внутреннему узлу соответствует использование продукции F digit. Семантическое правило F.val:=digit.lexval определяет атрибут F.val в этом узле как имеющий значение 3, поскольку значение digit.lexval в дочернем узле равно 3. Аналогично в родительском по отношению к данному узлу атрибут T.val также имеет значение 3.

Рис. 50. Аннотированное дерево разбора для 3 *5+4п

Теперь рассмотрим узел продукции Т Т * F. Значение атрибута Т.vа1 в этом узле определяется следующим образом:

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

T T1 * F T.val:=T1.val× F.val

При использовании этого семантического правила в данном узле Т1.vа1 имеет значе­ние 3, полученное от левого наследника, а F.val — значение 5, полученное от правого наследника. Следовательно, в этом узле Т.val составляет 15.

Правило, связанное с продукцией для стартового нетерминала L E n, выводит значение выражения, порожденного E.

9.4 Наследуемые атрибуты

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

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

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

Пример 32

Рассмотрим синтаксически управляемое определение, представленное на рис. 51.

Объявление, порождаемое нетерминалом D в синтаксически управляемом определе­нии состоит из ключевого слова int или real, за которым следует список идентификаторов. Нетерминал Т имеет синтезируемый атрибут type, значение которого определяется ключевым словом объявления. Семантическое правило L.in := T.type, свя­занное с продукцией D T L, определяет наследуемый атрибут L.in как тип объявления. Затем приведенные правила распространяют этот тип вниз по дереву разбора с использованием атрибута L.in. Правила, связанные с продукциями для L, вызывают процедуру addtype для добавления типа каждого идентификатора к его записи в таблице символов (определяемой атрибутом entry).

Продукция

Семантические правила

D T L

L.in := T.type

T int

T.type := integer

T real

T.type := real

L L1 , id

L1 := L.in

addtype(id.entry, L.in)

L id

addtype(id.entry, L.in)

Рис. 51. Синтаксически управляемое определение с наследуемым атрибутом L.in

Рис. 52. Дерево разбора с наследуемыми атрибутами in в каждом узле, помеченном L

На рис. 52 показано аннотированное дерево разбора для предложения real id1, id2, id3 . Значение L.in в трех L-узлах дает тип идентификаторов id1, id2 и id3. Эти значения определяются вычислением значения атрибута T.type в левом дочернем по отношению к корню узле, а затем вычислением L.in в нисходящем порядке в трех L-узлах правого поддерева корневого узла. В каждом L-узле вызывается также процедура addtype для записи в таблицу символов информации о том, что идентификатор в правом дочернем узле имеет тип real.