Опубликован: 06.08.2007 | Уровень: профессионал | Доступ: платный
Дополнительный материал 1:

Семантика контекстно-свободных языков

< Лекция 11 || Дополнительный материал 1: 12345 || Дополнительный материал 2 >

Формальные свойства

Придадим теперь идее использования синтезированных и унаследованных атрибутов более точную и более общую форму.

Пусть имеется КС-грамматика G = (V, N, S, P), где V - (конечный) алфавит терминальных и нетерминальных символов; N \subseteq V - множество нетерминальных символов; S \in  N - "начальный "символ, не входящий в правые части правил, и P - множество правил.

Семантические правила дополняют G следующим образом. С каждым символом X \in  V связывается конечное множество атрибутов A(X). A(X) разбивается на два непересекающихся множества: множество синтезированных атрибутов A0(X) и множество унаследованных атрибутов A1(X). Множество A1(S) должно быть пустым (то есть начальный символ S не должен иметь унаследованных атрибутов); аналогично, множество A0(X) пусто, если X - терминальный символ. Каждый атрибут R из множества A(X) имеет (возможно, бесконечное) множество значений VR. Для каждого вхождения X в дерево вывода семантические правила позволяют определить одно значение из множества VR для соответствующего атрибута.

Пусть P состоит из m правил, и пусть p -е правило имеет вид

Xp0 -> Xp1Xp2...Xpnp ;
Пример 2.1.

где np > 0, X_{p0} \in  N и X_{pj} \in  V для 1 <= j <= np. Семантическими правилами называются функции fpjR, определ_нные для всех 1 <= p <= m, 0 <= j <= np и некоторых \alpha  \in  A_{0}(X_{pj}), если j = 0, или \alpha  \in  A_{1}(X_{pj}), если j > 0. Каждая такая функция представляет собой отображение из V_{\alpha 1} x V_{\alpha 2} x \dots  x V_{\alpha t} в VR для некоторого t = t(p, j, \alpha ) > 0, где все \alpha _{i} = \alpha _{i}(p, j, \alpha ) являются атрибутами некоторых Xpki, при 0 \le  k_{i} = k_{i}(p, j, \alpha ) \le  n_{p}, 1 \le  i \le  t. Другими словами, каждое семантическое правило отображает значения некоторых атрибутов символов X_{p0}, X_{p1}, \ldots X_{p_{n_p}} и значение некоторого атрибута символа X_{p_j}.

Грамматика ( таблица 1.1), например, представляется в виде G = ({0, 1, ".", B, L, N}, {B, L, N}, N, {B -> 0, B -> 1, L -> B, L -> LB, N -> L, N -> L.L}).

Атрибутами здесь являются

A_{0}(B) = \{ v\} , 	A_{1}(B) = \{ s\} ;
\\
A_{0}(L) = \{ v, l\} , 	A_{1}(L) = \{ s\} ;
\\
A_{0}(N) = \{ v\} , 	A_{1}(N) = \varnothing 
\\
и \ A_{0}(x) = A_{1}(x) = \varnothing

для x \in  \{ 0, 1, .\}. Множествами значений атрибутов будут Vv ={рациональные числа}, Vs = Vl = {целые числа}. Типичным примером правил вывода служит четвeртое правило X40 -> X41X42 , где n4 = 2, X40 = X41 = L, X42 = B. Так же типично и семантическое правило f40v, соответствующее этому правилу вывода. Оно определяет v(X40) через другие атрибуты; в данном случае f40v отображает Vv x Vv в Vv согласно формуле f40v(x, y) = x + y. (Это есть не что иное, как правило v(L1) = v(L2) + v(B) из ( таблица 1.1); используя довольно громоздкую запись, введeнную в предыдущем абзаце, получим:

t(4, 0, v) = 2, \alpha _{1}(4, 0, v) = \alpha _{2}(4, 0, v) = v,k_{1}(4, 0, v) = 1, k_{2}(4, 0, v) = 2).

Семантические правила используются для сопоставления цепочкам КС языка"значения" следующим образом1На самом деле значение здесь приписывается дереву вывода цепочки, а не ей самой. Если грамматика неоднозначна, это не одно и то же (см. последнюю страницу статьи). - Прим. перев. . Для любого вывода терминальной цепочки t из S при помощи синтаксических правил построим обычное дерево вывода. А именно, корнем дерева будет S, а каждый узел помечается либо терминальным символом, либо нетерминалом Xp0, соответствующим применению p -го правила для некоторого p ; в последнем случае у этого узла будет np непосредственных потомков.


Рис. 2.2.

Пусть теперь X - метка некоторого узла дерева и пусть R \in  A(X) - атрибут символа X. Если \alpha  \in  A_{0}(X), то \ X = X_{p0} для некоторого p, если же \alpha  \in  A_{1}(X), то \ X = X_{pj} для некоторых j и p. В обоих случаях дерево "в районе" этого узла имеет вид ( рис. 2.2). По определению атрибут \alpha имеет в этом узле значение v, если в соответствующем семантическом правиле

f_{pj\alpha }:V_{\alpha 1}x \dots  x V_{\alpha t}\to V_{\alpha }

все атрибуты \alpha _{1}, \dots  , \alpha _{t} уже определены и имеют в узлах с метками Xpk1 , ... , Xpkt значения v1, ... , vt соответственно, а v = f_{pj\alpha }(v_{1}, \dots  , v_{t}). Процесс вычисления атрибутов на дереве продолжается до тех пор, пока нельзя будет вычислить больше ни одного атрибута. Вычисленные в результате атрибуты корня дерева представляют собой "значение", соответствующее данному дереву вывода ( рис. 1.6).

Естественно потребовать, чтобы семантические правила давали возможность вычислить все атрибуты произвольного узла в любом дереве вывода. Если это условие выполняется, будем говорить, что семантические правила заданы корректно2В оригинале well defined. - Прим. ред. . Поскольку деревьев вывода, вообще говоря, бесконечно много, важно уметь определять по самой грамматике, являются ли корректными еe семантические правила.

Отметим, что этот метод определения семантики обладает такой же мощностью, как и всякий другой возможный метод, в том смысле, что значение любого атрибута в любом узле может произвольным образом зависеть от структуры всего дерева. Предположим, например, что в КС грамматике всем символам, кроме S, приписано по два унаследованных атрибута: l ("положение") и t ("дерево"), а всем нетерминалам, кроме того, по одному синтезированному атрибуту s ("поддерево"). Значениями l будут конечные последовательности положительных целых чисел \{a_1 \cdot a_2 \cdot \ldots \cdot a_k\}, определяющие местонахождение узла в дереве в соответствии с системой обозначения Дьюи. Атрибуты t и s представляют собой множество упорядоченных пар (l, X), где l - положение узла, а X - символ грамматики, обозначающий метку узла с положением l. Семантическими правилами для каждого синтаксического правила ( пример 2.1) служат

l(X_{pj})=
\left\{
\begin{aligned}
&l(X_{p0})\cdot j , & \text{ если } & X_{p0}\neq S;\\
&j, & \text{ если } & X_{p0}= S;\\
\end{aligned}
\right. 
\\l(X_{pj})=
\left\{
\begin{aligned}
&t(X_{p0}),  & \text{ если } & X_{p0}\neq S;\\
&s(X_{p0}), & \text{ если } & X_{p0}= S;\\
\end{aligned}
\right. ( 2.4)
s(X_{p0})=\{(l(X_{p0}),X_{p0}) \mid\ X_{p0} \neq S \} \cup \bigcup\limits_{j=1}^{n_{p}}} \{S(X_{pj}) \mid X_{pj} \in N \}

Следовательно, для дерева ( рис. 1.2), например, мы имеем

s(N) = {(1, L), (2, *), (3, L),
	(1.1, L), (1.2, B), (3.1, L), (3.2, B),
	(1.1.1, L), (1.1.2, B), (1.2.1, 1), (3.1.1, B), (3.2.1, 1),
	(1.1.1.1, L), (1.1.1.2, B), (1.1.2.1, 0), (3.1.1.1, 0),
	(1.1.1.1.1, B), (1.1.1.2.1, 1), (1.1.1.1.2.1, 1)}.

Ясно, что эта запись содержит всю информацию о дереве вывода. Согласно семантическим правилам (2.4), атрибут t во всех узлах (кроме корня) представляет собой множество, характеризующее всe дерево вывода; атрибут l определяет местонахождение этих узлов. Отсюда сразу следует, что любая мыслимая функция, определ_нная на дереве вывода, может быть представлена как атрибут произвольного узла, поскольку эта функция имеет вид f(t, l), для некоторого f. Аналогично, можно показать, что для определения значения, связанного с произвольным деревом вывода, достаточно только синтезированных атрибутов, поскольку синтезированный атрибут w, вычисляемый по формуле

w(X_{p0})=\{(0, \; X_{p0})\cup \bigcup\limits_{j=1}^{n_{p}}\{(j\cdot \alpha, X) \mid \\
(\alpha,X)\in w (X_{pj}), \; X_{pj}\in N\} ( 2.5)

в корне дерева полностью определяет всe дерево3В правой части формулы нужно добавить ещe член \bigcup_{j=1}^{n_{p}}\{(j\cdot 0, x) \mid x\notin N\}. - Прим. ред. . Каждое семантическое правило, определяемое методами этого раздела, можно рассматривать как функцию этого атрибута w. Следовательно, описанный общий метод по существу не более мощен, чем метод, вовсе не использующий наследованных атрибутов. Правда, это утверждение не следует понимать как практическую рекомендацию, поскольку семантические правила, не использующие унаследованных атрибутов, будут зачастую гораздо более сложными (а также менее понимаемыми и практичными), чем правила, включающие атрибуты обоих типов. Если допустить, чтобы атрибуты в каждом узле дерева могли зависеть от всего дерева, то семантические правила часто могут стать проще и будут лучше соответствовать нашему пониманию процесса вычисления.

< Лекция 11 || Дополнительный материал 1: 12345 || Дополнительный материал 2 >
Никита Барсуков
Никита Барсуков
Россия, СПБПУ
Николай Архипов
Николай Архипов
Россия, Екатеринбург, Уральский федеральный университет