В.А. Серебряков, М.П. Галочкин - Основы конструирования компиляторов (1134643), страница 16
Текст из файла (страница 16)
5.1:( [( 5.3. АТРИБУТНЫЕ ГРАММАТИКИ89(2) AS – конечное множество синтезируемых атрибутов;(3) AI – конечное множество наследуемых атрибутов, AS ∩ AI = ∅;(4) R – конечное множество семантических правил.Атрибутная грамматика AG сопоставляет каждому символу X из N ∪ Tмножество AS (X) синтезируемых атрибутов и множество AI (X) наследуемых атрибутов.
Множество всех синтезируемых атрибутов всех символов из N ∪ T обозначается AS , наследуемых – AI . Атрибуты разныхсимволов являются различными атрибутами. Будем обозначать атрибут a символа X как a(X). Значения атрибутов могут быть произвольных типов, например, представлять собой числа, строки, адреса памятии т.д.Пусть правило p из P имеет вид X0 → X1 X2 ...
Xn . Атрибутная грамматика AG сопоставляет каждому правилу p из P конечное множествоR(p) семантических правил видаa(Xi ) = f (b(Xj ), c(Xk ), ... , d(Xm ))где 0 6 j, k, ... , m 6 n, причем 1 6 i 6 n, если a(Xi ) ∈ AI (Xi ) (т.е. a(Xi ) –наследуемый атрибут), и i = 0, если a(Xi ) ∈ AS (Xi ) (т.е. a(Xi ) – синтезируемый атрибут).Таким образом, семантическое правило определяет значение атрибута a символа Xi на основе значений атрибутов b, c, . . .
, d символов Xj ,Xk , . . . , Xm соответственно.В частном случае длина n правой части правила может быть равнанулю, тогда будем говорить, что атрибут a символа Xi “получает в качестве значения константу”.В дальнейшем будем считать, что атрибутная грамматика не содержит семантических правил для вычисления атрибутов терминальныхсимволов. Предполагается, что атрибуты терминальных символов – либо предопределенные константы, либо доступны как результат работылексического анализатора.Пример 5.5. Рассмотрим атрибутную грамматику, позволяющую вычислитьзначение вещественного числа, представленного в десятичной записи. Здесь N ={N um, Int, F rac}, T = {digit, .}, S = N um, а правила вывода и семантическиеправила определяются следующим образом (верхние индексы используются дляссылки на разные вхождения одного и того же нетерминала):ГЛАВА 5.
ЭЛЕМЕНТЫ ТЕОРИИ ПЕРЕВОДА90N um → Int . F racv(N um) = v(Int) + v(F rac)p(F rac) = 1Int → ev(Int) = 0p(Int) = 0Int1 → digit Int2v(Int1 ) = v(digit) ∗ 10p(Intp(Int1 ) = p(Int2 ) + 1F rac → ev(F rac) = 0F rac1 → digit F rac2v(F rac1 ) = v(digit) ∗ 10−p(F racp(F rac2 ) = p(F rac1 ) + 12)+ v(Int2 )1)+ v(F rac2 )Для этой грамматикиAS (N um) = {v},AS (Int) = {v, p},AS (F rac) = {v},AI (N um) = ∅,AI (Int) = ∅,AI (F rac) = {p}.Пусть дана атрибутная грамматика AG и цепочка, принадлежащаяязыку, определяемому соответствующей G = (N, T, P, S). Сопоставимэтой цепочке “значение” следующим образом. Построим дерево разбораT этой цепочки в грамматике G. Каждый внутренний узел этого деревапомечается нетерминалом X0 , соответствующим применению p-го правила грамматики; таким образом, у этого узла будет n непосредственных потомков (рис.
5.2).;;; ;QРис. 5.2:Пусть теперь X – метка некоторого узла дерева и пусть a – атрибутсимвола X. Если a – синтезируемый атрибут, то X = X0 для некоторогоp ∈ P ; если же a – наследуемый атрибут, то X = Xj для некоторых p ∈ Pи 1 6 j 6 n. В обоих случаях дерево “в районе” этого узла имеет вид,приведенный на рис.
5.2. По определению, атрибут a имеет в этом узлезначение v, если в соответствующем семантическом правилеa(Xi ) = f (b(Xj ), c(Xk ), ... , d(Xm ))все атрибуты b, c, . . . , d уже определены и имеют в узлах с метками Xj ,Xk , . . . , Xm значения vj , vk , . . . , vm соответственно, а v = f (v1 , v2 , ... , vm ).5.3. АТРИБУТНЫЕ ГРАММАТИКИ91Процесс вычисления атрибутов на дереве продолжается до тех пор, пока нельзя будет вычислить больше ни одного атрибута. Вычисленные врезультате атрибуты корня дерева представляют собой “значение”, соответствующее данному дереву вывода.Заметим, что значение синтезируемого атрибута символа в узле синтаксического дерева вычисляется по атрибутам символов в потомкахэтого узла; значение наследуемого атрибута вычисляется по атрибутам“родителя’ и “соседей”.Атрибуты, сопоставленные вхождениям символов в дерево разбора,будем называть вхождениями атрибутов в дерево разбора, а дерево с сопоставленными каждой вершине атрибутами – атрибутированным деревом разбора.Пример 5.6.
Атрибутированное дерево для грамматики из предыдущего примера и цепочки w = 12.34 показано на рис. 5.3.1XP,QWGLJLWY Y S ,QWGLJLWY Y )UDFGLJLWY S ,QWY Y S Y S )UDFGLJLWY Y S )UDFY S HHРис. 5.3:Будем говорить, что семантические правила заданы корректно, если они позволяют вычислить все атрибуты произвольного узла в любомдереве вывода.Между вхождениями атрибутов в дерево разбора существуют зависимости, определяемые семантическими правилами, соответствующимипримененным синтаксическим правилам.
Эти зависимости могут бытьпредставлены в виде ориентированного графа следующим образом.Пусть T – дерево разбора. Сопоставим этому дереву ориентированный граф D(T ), узлами которого являются пары (n, a), где n – узел дерева T , a – атрибут символа, служащего меткой узла n. Граф содержитдугу из (n1 , a1 ) в (n2 , a2 ) тогда и только тогда, когда семантическое правило, вычисляющее атрибут a2 , непосредственно использует значениеГЛАВА 5. ЭЛЕМЕНТЫ ТЕОРИИ ПЕРЕВОДА92атрибута a1 .
Таким образом, узлами графа D(T ) являются атрибуты, которые нужно вычислить, а дуги определяют зависимости, подразумевающие, какие атрибуты вычисляются раньше, а какие позже.Пример 5.7. Граф зависимостей атрибутов для дерева разбора из предыдущего примера показан на рис. 5.4.Y1XP S1XPY,QW S,QWYGLJLWY,QW S,QWY,QW S,QWYGLJLW Y,QW S,QWYGLJLW Y,QW S,QWYGLJLW Y,QW S,QWРис. 5.4:Можно показать, что семантические правила являются корректными тогда и только тогда, когда для любого дерева вывода T соответствующий граф D(T ) не содержит циклов (т.е.
является ориентированнымациклическим графом).5.3.2Классы атрибутных грамматик и их реализацияВ общем виде реализация вычислителей для атрибутных грамматик вызывает значительные трудности. Это связано с тем, что множество значений атрибутов, связанных с данным деревом, приходится вычислятьв соответствии с зависимостями атрибутов, которые образуют ориентированный ациклический граф. На практике стараются осуществлять процесс вычисления атрибутов, привязывая его к тому или иному способуобхода дерева.
Рассматривают многовизитные, многопроходные и другие атрибутные вычислители. Это, как правило, ведет к ограничениюдопустимых зависимостей между атрибутами, поддерживаемых вычислителем.Простейшими подклассами атрибутных грамматик, вычисления всехатрибутов для которых может быть осуществлено одновременно с синтаксическим анализом, являются S-атрибутные и L-атрибутные грамматики.5.3.
АТРИБУТНЫЕ ГРАММАТИКИ93Определение. Атрибутная грамматика называется S-атрибутной, если она содержит только синтезируемые атрибуты.Нетрудно видеть, что для S-атрибутной грамматики на любом дереве разбора все атрибуты могут быть вычислены за один обход дереваснизу вверх. Таким образом, вычисление атрибутов можно делать параллельно с восходящим синтаксическим анализом, например, LR(1)анализом.Пример 5.8. Рассмотрим S-атрибутную грамматику для перевода арифметических выражений в ПОЛИЗ. Здесь атрибут v имеет строковый тип, k – обозначает операцию конкатенации. Правила вывода и семантические правила определяются следующим образомE1 → E2 + Tv(E 1 ) = v(E 2 ) k v(T ) k 0 +0E→Tv(E) = v(T )T →T ∗Fv(T 1 ) = v(T 2 ) k v(F ) k 0 ∗0T →Fv(T ) = v(F )F → idv(F ) = v(id)F → (E)v(F ) = v(E)Определение. Атрибутная грамматика называется L-атрибутной, если любой наследуемый атрибут любого символа Xj из правой частикаждого правила X0 → X1 X2 ...
Xn грамматики зависит только от(1) атрибутов символов X1 , X2 , . . . , Xj−1 , находящихся в правиле слева от Xj , и(2) наследуемых атрибутов символа X0 .Заметим, что каждая S-атрибутная грамматика является L-атрибутной.Все атрибуты на любом дереве для L-атрибутной грамматики могут бытьвычислены за один обход дерева сверху-вниз слева-направо. Таким образом, вычисление атрибутов можно осуществлять параллельно с нисходящим синтаксическим анализом, например, LL(1)-анализом или рекурсивным спуском.В случае рекурсивного спуска в каждой функции, соответствующейнетерминалу, надо определить формальные параметры, передаваемыепо значению, для наследуемых атрибутов, и формальные параметры,передаваемые по ссылке, для синтезируемых атрибутов.
В качестве примера рассмотрим реализацию атрибутной грамматики из примера 5.5(нетрудно видеть, что грамматика является L-атрибутной).94ГЛАВА 5. ЭЛЕМЕНТЫ ТЕОРИИ ПЕРЕВОДАvoid int_part(float * V0, int * P0){if (Map[InSym]==Digit){ int I=InSym;float V2;int P2;InSym=getInSym();int_part(&V2,&P2);*V0=I*exp(P2*ln(10))+V2;*P0=P2+1;else {*V0=0;*P0=0;}}void fract_part(float * V0, int P0){if (Map[InSym]==Digit){ int I=InSym;float V2;int P2=P0+1;InSym=getInSym();fract_part(&V2,P2);*V0=I*exp(-P0*ln(10))+V2;else {*V0=0;}}void number(){ float V1,V3,V0;int P;int_part(&V1,&P);if (InSym!=’.’) error();fract_part(&V3,1);V0=V1+V3;}5.3.3Язык описания атрибутных грамматикФормализм атрибутных грамматик оказался очень удобным средствомдля описания семантики языков программирования.
Вместе с тем выяснилось, что реализация вычислителей для атрибутных грамматик общего вида сталкивается с большими трудностями. В связи с этим былосделано множество попыток рассматривать те или иные классы атрибутных грамматик, обладающих “хорошими” свойствами. К числу таких свойств относятся прежде всего простота алгоритма проверки атрибутной грамматики на зацикленность и простота алгоритма вычисления атрибутов для атрибутных грамматик данного класса.Атрибутные грамматики использовались для описания семантики языков программирования и было создано несколько систем автоматиза-5.3.