Теория и реализация языков программирования

       

Проверка на зацикленность


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

Пусть T - произвольное дерево вывода, соответствующее данной грамматике; метками концевых узлов могут быть только терминальные символы, корню же разрешим иметь меткой не только аксиому, но и любой символ из V . Тогда можно определить ориентированный граф D(T), соответствующий T, взяв в качестве его узлов упорядоченные пары (X,

Проверка на зацикленность
), где X - узел дерева T, а
Проверка на зацикленность
- атрибут символа, служащего меткой узла X. Дуга из (X1;
Проверка на зацикленность
1) в (X2,
Проверка на зацикленность
2) проводится в том и только в том случае, когда семантическое правило, вычисляющее атрибут
Проверка на зацикленность
2, непосредственно использует значение атрибута
Проверка на зацикленность
1. Например, если T - дерево (рис. 1.2), а в качестве семантических правил взяты правила (таблица 1.1), то орграф D(T) будет иметь такой вид:

Проверка на зацикленность

Рис. 3.1. 

Другими словами, узлами графа D(T) служат атрибуты, значения которых нужно вычислить, а дуги определяют зависимости, подразумевающие, какие атрибуты вычисляются раньше, а какие позже (рис. 1.6).

Ясно, что семантические правила являются корректными тогда и только тогда, когда ни один из орграфов D(T) не содержит ориентированного цикла. Дело в том, что если в графе нет ориентированных циклов, то можно применить хорошо известную процедуру, позволяющую присвоить значения всем атрибутам. Если же в некотором графе D(T) есть ориентированный цикл, то ввиду того что грамматика не содержит бесполезных правил, можно утверждать, что существует ориентированный цикл в некотором графе D(T), у которого меткой корня дерева T служит S. Для такого дерева T все атрибуты вычислить не уда_тся. Таким образом, задача "Являются ли семантические правила корректным?" сводится к задаче "Содержат ли орграфы D(T) ориентированные циклы?"


Каждый орграф D(T) можно рассматривать как суперпозицию меньших орграфов Dp, соответствующих правилам Xp0
Проверка на зацикленность
Xp1 ... Xpn грамматики, 1
Проверка на зацикленность
p
Проверка на зацикленность
m. В обозначениях разд. 2 орграф Dp имеет узлы (Xpj,
Проверка на зацикленность
) для 0
Проверка на зацикленность
j
Проверка на зацикленность
np,
Проверка на зацикленность
Проверка на зацикленность
A(Xpj) и дуги из (Xpki ,
Проверка на зацикленность
) в (Xpj ,
Проверка на зацикленность
) для 0
Проверка на зацикленность
j
Проверка на зацикленность
np,
Проверка на зацикленность
Проверка на зацикленность
A0(Xpj), если j = 0,
Проверка на зацикленность
Проверка на зацикленность
A1(Xpj ), если j > 0, ki = ki(p, j,
Проверка на зацикленность
),
Проверка на зацикленность
i =
Проверка на зацикленность
i(p, j,
Проверка на зацикленность
), 1
Проверка на зацикленность
i
Проверка на зацикленность
t(p, j,
Проверка на зацикленность
). Другими словами, Dp отражает связи, которые порождают все семантические правила, соответствующие p-му синтаксическому правилу. Например, шести правилам грамматики (таблица 1.1) соответствуют шесть следующих орграфов:

Проверка на зацикленность

Рис. 3.2. 

Орграф (рис. 3.1) получается в результате "объединения" таких подграфов. Вообще, если T имеет в качестве метки корня терминал, D(T) не содержит дуг. Если корень дерева T помечен нетерминальным символом, T имеет вид

Проверка на зацикленность

Рис. 3.3. 

для некоторого p, где Tj - дерево вывода, у которого корень помечен символом Xpj, где 1
Проверка на зацикленность
j
Проверка на зацикленность
np. В первом случае говорят, что T - дерево вывода типа 0, во втором случае T называется деревом вывода типа р. В соответствии с этим определением для того, чтобы по Dp, D(T1), ... , D(Tnp ) построить D(T), нужно для всех j, 1
Проверка на зацикленность
j
Проверка на зацикленность
np совместить узлы, соответствующие атрибутам символа Xpj графа Dp с соответствующими узлами (отвечающими тем же атрибутам корня дерева Tj) в графе D(Tj ).

Для проверки того, содержит ли граф D(T) ориентированный цикл, нам понадобится ещe одно понятие. Пусть p - номер правила вывода. Обозначим через Gj

произвольный орграф (1
Проверка на зацикленность
j
Проверка на зацикленность
np), множество узлов которого является подмножеством множества A(Xpj) атрибутов символа Xpj. Пусть

Dp[G1,..., Gnp ]

Пример 3.4.

(html, txt)

орграф, полученный из Dp добавлением дуг, идущих из (Xpj,
Проверка на зацикленность
) в (Xpj,
Проверка на зацикленность
0), если в графе Gj есть дуга из
Проверка на зацикленность
в
Проверка на зацикленность
0

Например, если

Проверка на зацикленность


и если D4 - ориентированный граф из (3.2), то D4(G1, G2) имеет вид

Проверка на зацикленность

Рис. 3.4. 

Теперь можно воспользоваться следующим алгоритмом. Для любого X
Проверка на зацикленность
V S(X) будет некоторым множеством ориентированных графов с узлами из A(X). Сначала для всех X
Проверка на зацикленность
N S(X) пусто, а для X =
Проверка на зацикленность
N S(X) состоит из единственного графа с множеством узлов A(X) и не содержащего дуг.


Будем добавлять к множествам S(X) новые орграфы при помощи следующей процедуры до тех пор, пока в S(X) не перестанут появляться новые элементы. Выберем целое p; 1
Проверка на зацикленность
p
Проверка на зацикленность
m и для каждого j, 1
Проверка на зацикленность
j
Проверка на зацикленность
np, выберем орграф D0j
Проверка на зацикленность
S(Xpj). Затем добавим в S(Xp0) орграф с множеством узлов A(Xpo), обладающий тем свойством, что в нeм дуга от
Проверка на зацикленность
к
Проверка на зацикленность
0 идeт тогда и только тогда, когда в орграфе

Проверка на зацикленность


(3.5)


существует ориентированный путь из (Xp0;
Проверка на зацикленность
) в (Xp0;
Проверка на зацикленность
'): Ясно, что этот процесс рано или поздно закончится и новые орграфы перестанут порождаться, поскольку вообще существует лишь конечное число ориентированных графов. В случае грамматики (таблица 1.1) алгоритм построит следующие множества:

Проверка на зацикленность


Пусть T - дерево вывода с корнем X, и пусть D'(T) - ориентированный граф с множеством узлов A(X), у которого есть дуга из
Проверка на зацикленность
в
Проверка на зацикленность
' тогда и только тогда, когда в D(T) существует ориентированный путь из (X,
Проверка на зацикленность
) в (X,
Проверка на зацикленность
'). Покажем, что после окончания работы описанного выше алгоритма для всех X
Проверка на зацикленность
V S(X) - это множество всех D'(T), где T - дерево вывода с корнем X 1)

. Действительно, построение не добавляет к S(X) новых ориентированных графов, не являющихся D'(T). Алгоритм можно даже легко обобщить так, чтобы для каждого графа из S(X) он печатал на выходе соответствующее дерево вывода T. Обратно, если T - дерево вывода, мы можем показать индукцией по числу узлов дерева T, что D'(T) принадлежит некоторому множеству S(X). В противном случае T должно иметь вид (3.3) и D(T) "составлен" из
Проверка на зацикленность
. По индукции и вследствие того, что при j
Проверка на зацикленность
j' из D(Tj) в D(Tj' ) не проходит дуг вне Dp, дуги в
Проверка на зацикленность
, составляющей рассматриваемый путь графа D(T), можно заменить соответствующими дугами в
Проверка на зацикленность
, где
Проверка на зацикленность
. Поэтому ориентированный граф, включаемый в S(Xp0) на базе
Проверка на зацикленность
, просто совпадает с D'(T).

Вышеприведeнный алгоритм решает задачу, поставленную в этом разделе.

Теорема. Семантические правила, добавленные к грамматике так, как это сделано в разд. 2, являются корректными тогда и только тогда, когда ни один из ориентированных графов (3.5) ни при каком выборе p и
Проверка на зацикленность
не содержит ориентированных циклов.

Доказательство. Если (3.5) содержит ориентированный цикл, то, как было показано выше, некоторый D(T) содержит ориентированный цикл. Наоборот, если T - дерево с наименьшим возможным числом улов, такое, что D(T) содержит ориентированный цикл, то T должно иметь вид (рис. 3.3), а D(T) "составляется" из
Проверка на зацикленность
. Из минимальности T следует, что ориентированный цикл включает по меньшей мере одну дугу графа Dp, и, следовательно, можно, рассуждая, как выше, все дуги, образующие этот цикл и лежащие в одном из графов
Проверка на зацикленность
, заменить дугами графа (3.5).


Содержание раздела